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 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; } }
static void cs_cmd_register(struct sourceinfo *si, int parc, char *parv[]) { struct channel *c; struct chanuser *cu; struct mychan *mc; char *name = parv[0]; char str[21]; hook_channel_register_check_t hdatac; hook_channel_req_t hdata; unsigned int fl; /* This command is not useful on registered channels, 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 (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REGISTER"); command_fail(si, fault_needmoreparams, _("To register a channel: REGISTER <#channel>")); return; } if (*name != '#') { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "REGISTER"); command_fail(si, fault_badparams, _("Syntax: REGISTER <#channel>")); return; } if (si->smu->flags & MU_WAITAUTH) { command_fail(si, fault_notverified, _("You need to verify your email address before you may register channels.")); return; } // make sure it isn't already registered if ((mc = mychan_find(name))) { if (! (mc->flags & MC_PRIVATE)) command_fail(si, fault_alreadyexists, _("\2%s\2 is already registered to \2%s\2."), mc->name, mychan_founder_names(mc)); else command_fail(si, fault_alreadyexists, _("\2%s\2 is already registered."), mc->name); return; } // make sure the channel exists if (!(c = channel_find(name))) { command_fail(si, fault_nosuch_target, _("The channel \2%s\2 must exist in order to register it."), name); return; } // make sure they're in it if (!(cu = chanuser_find(c, si->su))) { command_fail(si, fault_noprivs, _("You must be in \2%s\2 in order to register it."), name); return; } // make sure they're opped (or protected/owner on unreal/inspircd) if (!((CSTATUS_OP | CSTATUS_PROTECT | CSTATUS_OWNER) & cu->modes)) { command_fail(si, fault_noprivs, _("You must be a channel operator in \2%s\2 in order to register it."), name); return; } if (metadata_find(si->smu, "private:restrict:setter")) { command_fail(si, fault_noprivs, _("You have been restricted from registering channels by network staff.")); return; } if ((unsigned int)(CURRTIME - ratelimit_firsttime) > config_options.ratelimit_period) { ratelimit_count = 0; ratelimit_firsttime = CURRTIME; } if (ratelimit_count > config_options.ratelimit_uses && !has_priv(si, PRIV_FLOOD)) { command_fail(si, fault_toomany, _("The system is currently too busy to process your registration, please try again later.")); slog(LG_INFO, "CHANSERV:REGISTER:THROTTLED: \2%s\2 by \2%s\2", name, entity(si->smu)->name); return; } hdatac.si = si; hdatac.name = name; hdatac.chan = c; hdatac.approved = 0; hook_call_channel_can_register(&hdatac); if (hdatac.approved != 0) return; if (!myentity_can_register_channel(entity(si->smu))) { command_fail(si, fault_toomany, _("You have too many channels registered.")); return; } if (config_options.ratelimit_uses && config_options.ratelimit_period) ratelimit_count++; logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2", name); mc = mychan_add(name); mc->registered = CURRTIME; mc->used = CURRTIME; mc->mlock_on |= (CMODE_NOEXT | CMODE_TOPIC); if (c->limit == 0) mc->mlock_off |= CMODE_LIMIT; if (c->key == NULL) mc->mlock_off |= CMODE_KEY; mc->flags |= config_options.defcflags; chanacs_add(mc, entity(si->smu), custom_founder_check(), CURRTIME, entity(si->smu)); if (c->ts > 0) { snprintf(str, sizeof str, "%lu", (unsigned long)c->ts); metadata_add(mc, "private:channelts", str); } if (chansvs.deftemplates != NULL && *chansvs.deftemplates != '\0') metadata_add(mc, "private:templates", chansvs.deftemplates); command_success_nodata(si, _("\2%s\2 is now registered to \2%s\2."), mc->name, entity(si->smu)->name); hdata.si = si; hdata.mc = mc; hook_call_channel_register(&hdata); // Allow the hook to override this. fl = chanacs_source_flags(mc, si); cu = chanuser_find(mc->chan, si->su); if (cu == NULL) ; else if (ircd->uses_owner && fl & CA_USEOWNER && fl & CA_AUTOOP && !(cu->modes & CSTATUS_OWNER)) { modestack_mode_param(si->service->nick, mc->chan, MTYPE_ADD, ircd->owner_mchar[1], CLIENT_NAME(si->su)); cu->modes |= CSTATUS_OWNER; } else if (ircd->uses_protect && fl & CA_USEPROTECT && fl & CA_AUTOOP && !(cu->modes & CSTATUS_PROTECT)) { modestack_mode_param(si->service->nick, mc->chan, MTYPE_ADD, ircd->protect_mchar[1], CLIENT_NAME(si->su)); cu->modes |= CSTATUS_PROTECT; } }
static void cs_cmd_owner(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; char *nicklist; char *strtokctx; if (ircd->uses_owner == false) { command_fail(si, fault_noprivs, _("The IRCd software you are running does not support this feature.")); return; } if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "OWNER"); command_fail(si, fault_needmoreparams, _("Syntax: OWNER <#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_USEOWNER)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } nicklist = (!nick ? strdup(si->su->nick) : strdup(nick)); nick = strtok_r(nicklist, " ", &strtokctx); do { if (invert_purpose(si, parc, chan, &nick, '-', &cs_cmd_deowner)) continue; /* figure out who we're going to op */ if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); continue; } if (is_internal_client(tu)) continue; /* SECURE check; we can skip this if sender == target, because we already verified */ if ((si->su != tu) && (mc->flags & MC_SECURE) && !chanacs_user_has_flag(mc, tu, CA_OP) && !chanacs_user_has_flag(mc, tu, CA_AUTOOP)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); command_fail(si, fault_noprivs, _("\2%s\2 has the SECURE option enabled, and \2%s\2 does not have appropriate access."), mc->name, tu->nick); continue; } 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); continue; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, ircd->owner_mchar[1], CLIENT_NAME(tu)); cu->modes |= CSTATUS_OWNER; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been set as owner on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "OWNER: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been set as owner on \2%s\2."), tu->nick, mc->name); } while ((nick = strtok_r(NULL, " ", &strtokctx)) != NULL); free(nicklist); }
static void cs_cmd_halfop(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 (!ircd->uses_halfops) { command_fail(si, fault_noprivs, _("Your IRC server does not support halfops.")); return; } if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "HALFOP"); command_fail(si, fault_needmoreparams, _("Syntax: HALFOP <#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_HALFOP)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } /* figure out who we're going to halfop */ 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; /* SECURE check; we can skip this if sender == target, because we already verified */ if ((si->su != tu) && (mc->flags & MC_SECURE) && !chanacs_user_has_flag(mc, tu, CA_HALFOP) && !chanacs_user_has_flag(mc, tu, CA_AUTOHALFOP)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); command_fail(si, fault_noprivs, _("\2%s\2 has the SECURE option enabled, and \2%s\2 does not have appropriate access."), mc->name, tu->nick); 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_ADD, 'h', CLIENT_NAME(tu)); cu->modes |= ircd->halfops_mode; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been halfopped on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "HALFOP: \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 halfopped on \2%s\2."), tu->nick, mc->name); }
static void cs_cmd_deowner(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 (ircd->uses_owner == false) { command_fail(si, fault_noprivs, _("The IRCd software you are running does not support this feature.")); return; } if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "DEOWNER"); command_fail(si, fault_needmoreparams, _("Syntax: DEOWNER <#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_USEOWNER)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } /* figure out who we're going to deop */ 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, ircd->owner_mchar[1], CLIENT_NAME(tu)); cu->modes &= ~CSTATUS_OWNER; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been unset as owner on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "DEOWNER: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been unset as owner on \2%s\2."), tu->nick, mc->name); }
static void cs_cmd_up(sourceinfo_t *si, int parc, char *parv[]) { chanuser_t *cu; mychan_t *mc; char *name = parv[0]; char *chan = parv[0]; int fl; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UP"); command_fail(si, fault_needmoreparams, "Syntax: UP <#channel>"); return; } if (!(mc = mychan_find(name))) { command_fail(si, fault_nosuch_target, "\2%s\2 is not registered.", name); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, "\2%s\2 is closed.", name); return; } if (metadata_find(mc, "private:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), chan); return; } if (!mc->chan) { command_fail(si, fault_nosuch_target, "\2%s\2 does not exist.", name); return; } if (!si->su) return; // needs to be done over IRC if (chanacs_source_has_flag(mc, si, CA_SUSPENDED)) { command_fail(si, fault_noprivs, _("Your access in %s is \2suspended\2."), chan); return; } cu = chanuser_find(mc->chan, si->su); if (!cu) { command_fail(si, fault_nosuch_target, "You are not on \2%s\2.", mc->name); return; } fl = chanacs_user_flags(mc, cu->user); // Don't check NOOP, because they are explicitly requesting status if (ircd->uses_owner) { if (fl & CA_USEOWNER) { if (fl & CA_AUTOOP && !(ircd->owner_mode & cu->modes)) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, ircd->owner_mchar[1], CLIENT_NAME(cu->user)); cu->modes |= ircd->owner_mode; } } } if (ircd->uses_protect) { if (fl & CA_USEPROTECT) { if (fl & CA_AUTOOP && !(ircd->protect_mode & cu->modes) && !(ircd->uses_owner && cu->modes & ircd->owner_mode)) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, ircd->protect_mchar[1], CLIENT_NAME(cu->user)); cu->modes |= ircd->protect_mode; } } } if (fl & (CA_AUTOOP | CA_OP)) { if (fl & CA_AUTOOP && !(CSTATUS_OP & cu->modes)) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, 'o', CLIENT_NAME(cu->user)); cu->modes |= CSTATUS_OP; } } if (ircd->uses_halfops) { if (fl & (CA_AUTOHALFOP | CA_HALFOP)) { if (fl & CA_AUTOHALFOP && !(ircd->halfops_mode & cu->modes)) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, ircd->halfops_mchar[1], CLIENT_NAME(cu->user)); cu->modes |= ircd->halfops_mode; } } } if (fl & (CA_AUTOVOICE | CA_VOICE)) { if (fl & CA_AUTOVOICE && !(CSTATUS_VOICE & cu->modes)) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, 'v', CLIENT_NAME(cu->user)); cu->modes |= CSTATUS_VOICE; } } command_success_nodata(si, "Upped successfully on \2%s\2.", mc->name); }
static void cs_cmd_unban(struct sourceinfo *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; struct channel *c = channel_find(channel); struct mychan *mc = mychan_find(channel); struct user *tu; struct chanban *cb; if (si->su == NULL) { command_fail(si, fault_noprivs, STR_IRC_COMMAND_ONLY, "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, STR_IS_NOT_REGISTERED, channel); return; } if (!c) { command_fail(si, fault_nosuch_target, STR_CHANNEL_IS_EMPTY, channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, STR_NOT_LOGGED_IN); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE) && !chanacs_source_has_flag(mc, si, CA_EXEMPT)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } tu = si->su; { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; unsigned 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, ngettext(N_("Unbanned \2%s\2 on \2%s\2 (%u ban removed)."), N_("Unbanned \2%s\2 on \2%s\2 (%u bans removed)."), count), target, channel, count); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } }
static void cs_cmd_halfop(char *origin) { char *chan = strtok(NULL, " "); char *nick = strtok(NULL, " "); mychan_t *mc; user_t *u, *tu; chanuser_t *cu; if (!ircd->uses_halfops) { notice(chansvs.nick, origin, "Your IRC server does not support halfops."); return; } if (!chan) { notice(chansvs.nick, origin, STR_INSUFFICIENT_PARAMS, "HALFOP"); notice(chansvs.nick, origin, "Syntax: HALFOP <#channel> [nickname]"); return; } mc = mychan_find(chan); if (!mc) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", chan); return; } u = user_find_named(origin); if (!chanacs_user_has_flag(mc, u, CA_HALFOP)) { 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; } /* figure out who we're going to halfop */ if (!nick) tu = u; else { if (!(tu = user_find_named(nick))) { notice(chansvs.nick, origin, "\2%s\2 is not online.", nick); return; } } if (is_internal_client(tu)) return; /* SECURE check; we can skip this if sender == target, because we already verified */ if ((u != tu) && (mc->flags & MC_SECURE) && !chanacs_user_has_flag(mc, tu, CA_HALFOP) && !chanacs_user_has_flag(mc, tu, CA_AUTOHALFOP)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation.", mc->name); notice(chansvs.nick, origin, "\2%s\2 has the SECURE option enabled, and \2%s\2 does not have appropriate access.", mc->name, tu->nick); return; } cu = chanuser_find(mc->chan, tu); if (!cu) { notice(chansvs.nick, origin, "\2%s\2 is not on \2%s\2.", tu->nick, mc->name); return; } modestack_mode_param(chansvs.nick, chan, MTYPE_ADD, 'h', CLIENT_NAME(tu)); cu->modes |= ircd->halfops_mode; /* TODO: Add which username had access to perform the command */ if (tu != u) notice(chansvs.nick, tu->nick, "You have been halfopped on %s by %s", mc->name, origin); logcommand(chansvs.me, u, CMDLOG_SET, "%s HALFOP %s!%s@%s", mc->name, tu->nick, tu->user, tu->vhost); if (!chanuser_find(mc->chan, u)) notice(chansvs.nick, origin, "\2%s\2 has been halfopped on \2%s\2.", tu->nick, mc->name); }
static void cs_fcmd_dehalfop(char *origin, char *chan) { char *nick; mychan_t *mc; user_t *u, *tu; chanuser_t *cu; if (!ircd->uses_halfops) { notice(chansvs.nick, origin, "Your IRC server does not support halfops."); return; } mc = mychan_find(chan); if (!mc) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", chan); return; } u = user_find_named(origin); if (!chanacs_user_has_flag(mc, u, CA_HALFOP)) { 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; } /* figure out who we're going to dehalfop */ nick = strtok(NULL, " "); do { if (!nick) tu = u; else { if (!(tu = user_find_named(nick))) { notice(chansvs.nick, origin, "\2%s\2 is not online.", nick); continue; } } if (is_internal_client(tu)) continue; cu = chanuser_find(mc->chan, tu); if (!cu) { notice(chansvs.nick, origin, "\2%s\2 is not on \2%s\2.", tu->nick, mc->name); continue; } modestack_mode_param(chansvs.nick, chan, MTYPE_DEL, 'h', CLIENT_NAME(tu)); cu->modes &= ~ircd->halfops_mode; logcommand(chansvs.me, u, CMDLOG_SET, "%s DEHALFOP %s!%s@%s", mc->name, tu->nick, tu->user, tu->vhost); } while ((nick = strtok(NULL, " ")) != NULL); }
static void cs_cmd_down(sourceinfo_t *si, int parc, char *parv[]) { chanuser_t *cu; mychan_t *mc; char *name = parv[0]; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "DOWN"); command_fail(si, fault_needmoreparams, "Syntax: DOWN <#channel>"); return; } if (!(mc = mychan_find(name))) { command_fail(si, fault_nosuch_target, "\2%s\2 is not registered.", name); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, "\2%s\2 is closed.", name); return; } if (!mc->chan) { command_fail(si, fault_nosuch_target, "\2%s\2 does not exist.", name); return; } if (!si->su) return; // needs to be done over IRC cu = chanuser_find(mc->chan, si->su); if (!cu) { command_fail(si, fault_nosuch_target, "You are not on \2%s\2.", mc->name); return; } chanacs_user_flags(mc, cu->user); // Don't check NOOP, because they are explicitly requesting status if (ircd->uses_owner) { if (ircd->owner_mode & cu->modes) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, ircd->owner_mchar[1], CLIENT_NAME(cu->user)); cu->modes &= ~ircd->owner_mode; } } if (ircd->uses_protect) { if (ircd->protect_mode & cu->modes) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, ircd->protect_mchar[1], CLIENT_NAME(cu->user)); cu->modes &= ~ircd->protect_mode; } } if ((CSTATUS_OP & cu->modes)) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, 'o', CLIENT_NAME(cu->user)); cu->modes &= ~CSTATUS_OP; } if (ircd->uses_halfops) { if (ircd->halfops_mode & cu->modes) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, ircd->halfops_mchar[1], CLIENT_NAME(cu->user)); cu->modes &= ~ircd->halfops_mode; } } if ((CSTATUS_VOICE & cu->modes)) { modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, 'v', CLIENT_NAME(cu->user)); cu->modes &= ~CSTATUS_VOICE; } command_success_nodata(si, "Downed successfully on \2%s\2.", mc->name); }
static void cs_cmd_voice(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; char *nicklist; char *strtokctx; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "VOICE"); command_fail(si, fault_needmoreparams, _("Syntax: VOICE <#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 (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } nicklist = (!nick ? strdup(si->su->nick) : strdup(nick)); nick = strtok_r(nicklist, " ", &strtokctx); do { if (invert_purpose(si, parc, chan, &nick, '-', &cs_cmd_devoice)) continue; /* figure out who we're going to voice */ if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); continue; } if (!chanacs_source_has_flag(mc, si, CA_VOICE) && (tu != si->su || !chanacs_source_has_flag(mc, si, CA_AUTOVOICE))) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); continue; } if (is_internal_client(tu)) continue; 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); continue; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, 'v', CLIENT_NAME(tu)); cu->modes |= CSTATUS_VOICE; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been voiced on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "VOICE: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been voiced on \2%s\2."), tu->nick, mc->name); } while ((nick = strtok_r(NULL, " ", &strtokctx)) != NULL); free(nicklist); }