diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/cs_xop.c | 724 |
1 files changed, 432 insertions, 292 deletions
diff --git a/src/core/cs_xop.c b/src/core/cs_xop.c index abbddb75b..c258798f6 100644 --- a/src/core/cs_xop.c +++ b/src/core/cs_xop.c @@ -15,17 +15,37 @@ #include "module.h" -int do_xop(User * u, const char *xname, int xlev, int *xmsgs); -int do_aop(User * u); -int do_hop(User * u); -int do_sop(User * u); -int do_vop(User * u); +void myChanServHelp(User *u); -void myChanServHelp(User * u); +enum +{ + XOP_AOP, + XOP_SOP, + XOP_VOP, + XOP_HOP, + XOP_TYPES +}; + +enum +{ + XOP_DISABLED, + XOP_NICKS_ONLY, + XOP_ADDED, + XOP_MOVED, + XOP_NO_SUCH_ENTRY, + XOP_NOT_FOUND, + XOP_NO_MATCH, + XOP_DELETED, + XOP_DELETED_ONE, + XOP_DELETED_SEVERAL, + XOP_LIST_EMPTY, + XOP_LIST_HEADER, + XOP_CLEAR, + XOP_MESSAGES +}; -int xop_msgs[4][14] = { - {CHAN_AOP_SYNTAX, - CHAN_AOP_DISABLED, +int xop_msgs[XOP_TYPES][XOP_MESSAGES] = { + {CHAN_AOP_DISABLED, CHAN_AOP_NICKS_ONLY, CHAN_AOP_ADDED, CHAN_AOP_MOVED, @@ -38,8 +58,7 @@ int xop_msgs[4][14] = { CHAN_AOP_LIST_EMPTY, CHAN_AOP_LIST_HEADER, CHAN_AOP_CLEAR}, - {CHAN_SOP_SYNTAX, - CHAN_SOP_DISABLED, + {CHAN_SOP_DISABLED, CHAN_SOP_NICKS_ONLY, CHAN_SOP_ADDED, CHAN_SOP_MOVED, @@ -52,8 +71,7 @@ int xop_msgs[4][14] = { CHAN_SOP_LIST_EMPTY, CHAN_SOP_LIST_HEADER, CHAN_SOP_CLEAR}, - {CHAN_VOP_SYNTAX, - CHAN_VOP_DISABLED, + {CHAN_VOP_DISABLED, CHAN_VOP_NICKS_ONLY, CHAN_VOP_ADDED, CHAN_VOP_MOVED, @@ -66,8 +84,7 @@ int xop_msgs[4][14] = { CHAN_VOP_LIST_EMPTY, CHAN_VOP_LIST_HEADER, CHAN_VOP_CLEAR}, - {CHAN_HOP_SYNTAX, - CHAN_HOP_DISABLED, + {CHAN_HOP_DISABLED, CHAN_HOP_NICKS_ONLY, CHAN_HOP_ADDED, CHAN_HOP_MOVED, @@ -82,230 +99,76 @@ int xop_msgs[4][14] = { CHAN_HOP_CLEAR} }; -class CSXOP : public Module +class XOPBase : public Command { - public: - CSXOP(const std::string &modname, const std::string &creator) : Module(modname, creator) + private: + CommandResult DoAdd(User *u, std::vector<std::string> ¶ms, ChannelInfo *ci, int level, int *messages) { - Command *c; - - this->SetAuthor("Anope"); - this->SetVersion("$Id$"); - this->SetType(CORE); + const char *nick = params.size() > 2 ? params[2].c_str() : NULL; + ChanAccess *access; + int change = 0; + char event_access[BUFSIZE]; - c = createCommand("AOP", do_aop, NULL, CHAN_HELP_AOP, -1, -1, -1, -1); - this->AddCommand(CHANSERV, c, MOD_UNIQUE); - if (ircd->halfop) + if (!nick) { - c = createCommand("HOP", do_hop, NULL, CHAN_HELP_HOP, -1, -1, -1, -1); - this->AddCommand(CHANSERV, c, MOD_UNIQUE); + this->OnSyntaxError(u); + return MOD_CONT; } - c = createCommand("SOP", do_sop, NULL, CHAN_HELP_SOP, -1, -1, -1, -1); - this->AddCommand(CHANSERV, c, MOD_UNIQUE); - c = createCommand("VOP", do_vop, NULL, CHAN_HELP_VOP, -1, -1, -1, -1); - this->AddCommand(CHANSERV, c, MOD_UNIQUE); - - this->SetChanHelp(myChanServHelp); - } -}; - - - -/** - * Add the help response to anopes /cs help output. - * @param u The user who is requesting help - **/ -void myChanServHelp(User * u) -{ - notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SOP); - notice_lang(s_ChanServ, u, CHAN_HELP_CMD_AOP); - if (ircd->halfop) { - notice_lang(s_ChanServ, u, CHAN_HELP_CMD_HOP); - } - notice_lang(s_ChanServ, u, CHAN_HELP_CMD_VOP); -} - -/** - * The /cs xop command. - * @param u The user who issued the command - * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. - **/ -int do_aop(User * u) -{ - return do_xop(u, "AOP", ACCESS_AOP, xop_msgs[0]); -} - -/*************************************************************************/ - -int do_hop(User * u) -{ - return do_xop(u, "HOP", ACCESS_HOP, xop_msgs[3]); -} - -/*************************************************************************/ - -int do_sop(User * u) -{ - return do_xop(u, "SOP", ACCESS_SOP, xop_msgs[1]); -} - -/*************************************************************************/ - -int do_vop(User * u) -{ - return do_xop(u, "VOP", ACCESS_VOP, xop_msgs[2]); -} - -/* `last' is set to the last index this routine was called with - * `perm' is incremented whenever a permission-denied error occurs - */ - -int xop_del(User * u, ChannelInfo * ci, ChanAccess * access, int *perm, int uacc, int xlev) -{ - char *nick = access->nc->display; - if (!access->in_use || access->level != xlev) - return 0; - if (!is_services_admin(u) && uacc <= access->level) { - (*perm)++; - return 0; - } - access->nc = NULL; - access->in_use = 0; - send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, nick); - return 1; -} - -int xop_del_callback(User * u, int num, va_list args) -{ - ChannelInfo *ci = va_arg(args, ChannelInfo *); - int *last = va_arg(args, int *); - int *perm = va_arg(args, int *); - int uacc = va_arg(args, int); - int xlev = va_arg(args, int); - - if (num < 1 || num > ci->accesscount) - return 0; - *last = num; - - return xop_del(u, ci, &ci->access[num - 1], perm, uacc, xlev); -} - - -int xop_list(User * u, int index, ChannelInfo * ci, - int *sent_header, int xlev, int xmsg) -{ - ChanAccess *access = &ci->access[index]; - - if (!access->in_use || access->level != xlev) - return 0; - - if (!*sent_header) { - notice_lang(s_ChanServ, u, xmsg, ci->name); - *sent_header = 1; - } - notice_lang(s_ChanServ, u, CHAN_XOP_LIST_FORMAT, index + 1, - access->nc->display); - return 1; -} - -int xop_list_callback(User * u, int num, va_list args) -{ - ChannelInfo *ci = va_arg(args, ChannelInfo *); - int *sent_header = va_arg(args, int *); - int xlev = va_arg(args, int); - int xmsg = va_arg(args, int); - - if (num < 1 || num > ci->accesscount) - return 0; - - return xop_list(u, num - 1, ci, sent_header, xlev, xmsg); -} - - -int do_xop(User * u, const char *xname, int xlev, int *xmsgs) -{ - char *chan = strtok(NULL, " "); - char *cmd = strtok(NULL, " "); - char *nick = strtok(NULL, " "); - char event_access[BUFSIZE]; - - ChannelInfo *ci; - NickAlias *na; - NickCore *nc; - - unsigned i; - int change = 0; - short ulev; - int is_list = (cmd && stricmp(cmd, "LIST") == 0); - int is_servadmin = is_services_admin(u); - ChanAccess *access; - - /* If CLEAR, we don't need any parameters. - * If LIST, we don't *require* any parameters, but we can take any. - * If DEL or ADD we require a nick. */ - if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : !nick)) { - syntax_error(s_ChanServ, u, xname, xmsgs[0]); - } else if (!(ci = cs_findchan(chan))) { - notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); - } else if (ci->flags & CI_VERBOTEN) { - notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); - } else if (!(ci->flags & CI_XOP)) { - notice_lang(s_ChanServ, u, CHAN_XOP_ACCESS, s_ChanServ); - } else if (stricmp(cmd, "ADD") == 0) { - if (readonly) { - notice_lang(s_ChanServ, u, xmsgs[1]); + if (readonly) + { + notice_lang(s_ChanServ, u, messages[XOP_DISABLED]); return MOD_CONT; } - ulev = get_access(u, ci); + short ulev = get_access(u, ci); - if ((xlev >= ulev || ulev < ACCESS_AOP) && !is_servadmin) { + if ((level >= ulev || ulev < ACCESS_AOP) && !is_services_admin(u)) + { notice_lang(s_ChanServ, u, PERMISSION_DENIED); return MOD_CONT; } - na = findnick(nick); - if (!na) { - notice_lang(s_ChanServ, u, xmsgs[2]); + NickAlias *na = findnick(nick); + if (!na) + { + notice_lang(s_ChanServ, u, messages[XOP_NICKS_ONLY]); return MOD_CONT; - } else if (na->status & NS_VERBOTEN) { + } + else if (na->status & NS_VERBOTEN) + { notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, na->nick); return MOD_CONT; } - nc = na->nc; - for (access = ci->access, i = 0; i < ci->accesscount; - access++, i++) { - if (access->nc == nc) { + NickCore *nc = na->nc; + for (access = ci->access, i = 0; i < ci->accesscount; ++access, ++i) + { + if (access->nc == nc) + { /** * Patch provided by PopCorn to prevert AOP's reducing SOP's levels **/ - if ((access->level >= ulev) && (!is_servadmin)) { + if (access->level >= ulev && !is_services_admin(u)) + { notice_lang(s_ChanServ, u, PERMISSION_DENIED); return MOD_CONT; } - change++; + ++change; break; } } - if (!change) { - /* All entries should be in use so we no longer need - * to go over the entire list.. - for (i = 0; i < ci->accesscount; i++) - if (!ci->access[i].in_use) - break; - */ - - if (i < CSAccessMax) { - ci->accesscount++; - ci->access = - static_cast<ChanAccess *>(srealloc(ci->access, - sizeof(ChanAccess) * ci->accesscount)); - } else { - notice_lang(s_ChanServ, u, CHAN_XOP_REACHED_LIMIT, - CSAccessMax); + if (!change) + { + if (i < CSAccessMax) + { + ++ci->accesscount; + ci->access = static_cast<ChanAccess *>(srealloc(ci->access, sizeof(ChanAccess) * ci->accesscount)); + } + else + { + notice_lang(s_ChanServ, u, CHAN_XOP_REACHED_LIMIT, CSAccessMax); return MOD_CONT; } @@ -321,100 +184,126 @@ int do_xop(User * u, const char *xname, int xlev, int *xmsgs) snprintf(event_access, BUFSIZE, "%d", access->level); - if (!change) { - send_event(EVENT_ACCESS_ADD, 4, ci->name, u->nick, na->nick, - event_access); - notice_lang(s_ChanServ, u, xmsgs[3], access->nc->display, - ci->name); - } else { - send_event(EVENT_ACCESS_CHANGE, 4, ci->name, u->nick, na->nick, - event_access); - notice_lang(s_ChanServ, u, xmsgs[4], access->nc->display, - ci->name); + if (!change) + { + send_event(EVENT_ACCESS_ADD, 4, ci->name, u->nick, na->nick, event_access); + notice_lang(s_ChanServ, u, messages[XOP_ADDED], access->nc->display, ci->name); + } + else + { + send_event(EVENT_ACCESS_CHANGE, 4, ci->name, u->nick, na->nick, event_access); + notice_lang(s_ChanServ, u, messages[XOP_MOVED], access->nc->display, ci->name); } - } else if (stricmp(cmd, "DEL") == 0) { + return MOD_CONT; + } + + CommandResult DoDel(User *u, std::vector<std::string> ¶ms, ChannelInfo *ci, int level, int *messages) + { + const char *nick = params.size() > 2 ? params[2].c_str() : NULL; + ChanAccess *access; + int deleted, a, b; - if (readonly) { - notice_lang(s_ChanServ, u, xmsgs[1]); + + if (!nick) + { + this->OnSyntaxError(u); + return MOD_CONT; + } + + if (readonly) + { + notice_lang(s_ChanServ, u, messages[XOP_DISABLED]); return MOD_CONT; } - if (ci->accesscount == 0) { - notice_lang(s_ChanServ, u, xmsgs[11], chan); + if (!ci->accesscount) + { + notice_lang(s_ChanServ, u, messages[XOP_LIST_EMPTY], ci->name); return MOD_CONT; } - ulev = get_access(u, ci); + short ulev = get_access(u, ci); - if ((xlev >= ulev || ulev < ACCESS_AOP) && !is_servadmin) { + if ((level >= ulev || ulev < ACCESS_AOP) && !is_services_admin(u)) + { notice_lang(s_ChanServ, u, PERMISSION_DENIED); return MOD_CONT; } /* Special case: is it a number/list? Only do search if it isn't. */ - if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) { + if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) + { int count, last = -1, perm = 0; - deleted = - process_numlist(nick, &count, xop_del_callback, u, ci, - &last, &perm, ulev, xlev); - if (!deleted) { - if (perm) { + deleted = process_numlist(nick, &count, xop_del_callback, u, ci, &last, &perm, ulev, level); + if (!deleted) + { + if (perm) notice_lang(s_ChanServ, u, PERMISSION_DENIED); - } else if (count == 1) { - notice_lang(s_ChanServ, u, xmsgs[5], last, ci->name); - } else { - notice_lang(s_ChanServ, u, xmsgs[7], ci->name); - } - } else if (deleted == 1) { - notice_lang(s_ChanServ, u, xmsgs[9], ci->name); - } else { - notice_lang(s_ChanServ, u, xmsgs[10], deleted, ci->name); + else if (count == 1) + notice_lang(s_ChanServ, u, messages[XOP_NO_SUCH_ENTRY], last, ci->name); + else + notice_lang(s_ChanServ, u, messages[XOP_NO_MATCH], ci->name); } - } else { - na = findnick(nick); - if (!na) { + else if (deleted == 1) + notice_lang(s_ChanServ, u, messages[XOP_DELETED_ONE], ci->name); + else + notice_lang(s_ChanServ, u, messages[XOP_DELETED_SEVERAL], deleted, ci->name); + } + else + { + NickAlias *na = findnick(nick); + if (!na) + { notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, nick); return MOD_CONT; } nc = na->nc; - for (i = 0; i < ci->accesscount; i++) - if (ci->access[i].nc == nc && ci->access[i].level == xlev) + int i; + + for (i = 0; i < ci->accesscount; ++i) + if (ci->access[i].nc == nc && ci->access[i].level == level) break; - if (i == ci->accesscount) { - notice_lang(s_ChanServ, u, xmsgs[6], nick, chan); + if (i == ci->accesscount) + { + notice_lang(s_ChanServ, u, messages[XOP_NOT_FOUND], nick, chan); return MOD_CONT; } access = &ci->access[i]; - if (!is_servadmin && ulev <= access->level) { + if (!is_services_admin(u) && ulev <= access->level) + { deleted = 0; notice_lang(s_ChanServ, u, PERMISSION_DENIED); - } else { - notice_lang(s_ChanServ, u, xmsgs[8], access->nc->display, - ci->name); + } + else + { + notice_lang(s_ChanServ, u, messages[XOP_DELETED], access->nc->display, ci->name); access->nc = NULL; access->in_use = 0; - send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, - na->nick); + send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, na->nick); deleted = 1; } } - if (deleted) { + if (deleted) + { /* Reordering - DrStein */ - for (b = 0; b < ci->accesscount; b++) { - if (ci->access[b].in_use) { - for (a = 0; a < ci->accesscount; a++) { + for (b = 0; b < ci->accesscount; ++b) + { + if (ci->access[b].in_use) + { + for (a = 0; a < ci->accesscount; ++a) + { if (a > b) break; - if (!ci->access[a].in_use) { + if (!ci->access[a].in_use) + { ci->access[a].in_use = 1; ci->access[a].level = ci->access[b].level; ci->access[a].nc = ci->access[b].nc; - ci->access[a].last_seen = - ci->access[b].last_seen; + ci->access[a].last_seen = ci->access[b].last_seen; ci->access[b].nc = NULL; ci->access[b].in_use = 0; break; @@ -427,61 +316,79 @@ int do_xop(User * u, const char *xname, int xlev, int *xmsgs) * before sending the events! */ /* After reordering only the entries at the end could still be empty. * We ll free the places no longer in use... */ - for (i = ci->accesscount - 1; i >= 0; i--) { + for (i = ci->accesscount - 1; i >= 0; --i) + { if (ci->access[i].in_use == 1) break; - ci->accesscount--; + --ci->accesscount; } - ci->access = - static_cast<ChanAccess *>(srealloc(ci->access,sizeof(ChanAccess) * ci->accesscount)); + ci->access = static_cast<ChanAccess *>(srealloc(ci->access, sizeof(ChanAccess) * ci->accesscount)); } - } else if (stricmp(cmd, "LIST") == 0) { + + return MOD_CONT; + } + + CommandResult DoList(User *u, std::vector<std::string> ¶ms, ChannelInfo *ci, int level, int *messages) + { int sent_header = 0; + const char *nick = params.size() > 2 ? params[2].c_str() : NULL; - ulev = get_access(u, ci); + short ulev = get_access(u, ci); - if (!is_servadmin && ulev < ACCESS_AOP) { + if (!is_services_admin(u) && level < ACCESS_AOP) + { notice_lang(s_ChanServ, u, ACCESS_DENIED); return MOD_CONT; } - if (ci->accesscount == 0) { - notice_lang(s_ChanServ, u, xmsgs[11], ci->name); + if (!ci->accesscount) + { + notice_lang(s_ChanServ, u, messages[XOP_LIST_EMPTY], ci->name); return MOD_CONT; } - if (nick && strspn(nick, "1234567890,-") == strlen(nick)) { - process_numlist(nick, NULL, xop_list_callback, u, ci, - &sent_header, xlev, xmsgs[12]); - } else { - for (i = 0; i < ci->accesscount; i++) { - if (nick && ci->access[i].nc - && !match_wild_nocase(nick, ci->access[i].nc->display)) + if (nick && strspn(nick, "1234567890,-") == strlen(nick)) + process_numlist(nick, NULL, xop_list_callback, u, ci, &sent_header, level, messages[XOP_LIST_HEADER]); + else + { + for (int i = 0; i < ci->accesscount; ++i) + { + if (nick && ci->access[i].nc && !match_wild_nocase(nick, ci->access[i].nc->display)) continue; - xop_list(u, i, ci, &sent_header, xlev, xmsgs[12]); + xop_list(u, i, ci, &sent_header, level, message[XOP_LIST_HEADER]); } } if (!sent_header) - notice_lang(s_ChanServ, u, xmsgs[7], chan); - } else if (stricmp(cmd, "CLEAR") == 0) { - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + notice_lang(s_ChanServ, u, messages[XOP_NO_MATCH], ci->name); + + return MOD_CONT; + } + + CommandResult DoClear(User *u, std::vector<std::string> ¶ms, ChannelInfo *ci, int level, int *messages) + { + if (readonly) + { + notice_lang(s_ChanServ, u, messages[XOP_DISABLED]); return MOD_CONT; } - if (ci->accesscount == 0) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); + if (!ci->accesscount) + { + notice_lang(s_ChanServ, u, messages[XOP_LIST_EMPTY], ci->name); return MOD_CONT; } - if (!is_servadmin && !is_founder(u, ci)) { + if (!is_services_admin(u) && !is_founder(u, ci)) + { notice_lang(s_ChanServ, u, PERMISSION_DENIED); return MOD_CONT; } - for (i = 0; i < ci->accesscount; i++) { - if (ci->access[i].in_use && ci->access[i].level == xlev) { + for (int i = 0; i < ci->accesscount; ++i) + { + if (ci->access[i].in_use && ci->access[i].level == level) + { ci->access[i].nc = NULL; ci->access[i].in_use = 0; } @@ -489,11 +396,244 @@ int do_xop(User * u, const char *xname, int xlev, int *xmsgs) send_event(EVENT_ACCESS_CLEAR, 2, ci->name, u->nick); - notice_lang(s_ChanServ, u, xmsgs[13], ci->name); - } else { - syntax_error(s_ChanServ, u, xname, xmsgs[0]); + notice_lang(s_ChanServ, u, messages[XOP_CLEAR], ci->name); + + return MOD_CONT; + } + CommandResult DoXop(User *u, std::vector<std::string> ¶ms, int level, int *messages) + { + const char *chan = params[0].c_str(); + const char *cmd = params[1].c_str(); + + ChannelInfo *ci; + + if (!cmd) + this->OnSyntaxError(u); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + else if (!(ci->flags & CI_XOP)) + notice_lang(s_ChanServ, u, CHAN_XOP_ACCESS, s_ChanServ); + else if (!stricmp(cmd, "ADD")) + return this->DoAdd(u, params, ci, level, messages); + else if (!stricmp(cmd, "DEL")) + return this->DoDel(u, params, ci, level, messages); + else if (!stricmp(cmd, "LIST")) + return this->DoList(u, params, ci, level, messages); + else if (!stricmp(cmd, "CLEAR")) + return this->DoClear(u, params, ci, level, messages); + else + this->OnSyntaxError(u); + return MOD_CONT; + } + public: + XOPBase(const std::string &command) : Command(command, 2, 3) + { + } + + virtual ~XOPBase() + { + } + + virtual CommandResult Execute(User *u, std::vector<std::string> ¶ms) = 0; + + virtual bool OnHelp(User *u, const std::string &subcommand) = 0; + + virtual void OnSyntaxError(User *u) = 0; +}; + +class CommandCSAOP : public XOPBase +{ + public: + CommandCSAOP() : XOPBase("AOP") + { + } + + CommandResult Execute(User *u, std::vector<std::string> ¶ms) + { + return this->DoXop(u, params, ACCESS_AOP, xop_msgs[XOP_AOP]); + } + + bool OnHelp(User *u, const std::string &subcommand) + { + notice_land(s_ChanServ, u, CHAN_HELP_AOP); + return true; + } + + void OnSyntaxError(User *u) + { + syntax_error(s_ChanServ, u, "AOP", CHAN_AOP_SYNTAX); + } +}; + +class CommandCSHOP : public XOPBase +{ + public: + CommandCSHOP() : XOPBase("HOP") + { + } + + CommandResult Execute(User *u, std::vector<std::string> ¶ms) + { + return this->DoXop(u, params, ACCESS_HOP, xop_msgs[XOP_HOP]); + } + + bool OnHelp(User *u, const std::string &subcommand) + { + notice_land(s_ChanServ, u, CHAN_HELP_HOP); + return true; } - return MOD_CONT; + + void OnSyntaxError(User *u) + { + syntax_error(s_ChanServ, u, "HOP", CHAN_HOP_SYNTAX); + } +}; + +class CommandCSSOP : public XOPBase +{ + public: + CommandCSSOP() : XOPBase("SOP") + { + } + + CommandResult Execute(User *u, std::vector<std::string> ¶ms) + { + return this->DoXop(u, params, ACCESS_SOP, xop_msgs[XOP_SOP]); + } + + bool OnHelp(User *u, const std::string &subcommand) + { + notice_land(s_ChanServ, u, CHAN_HELP_SOP); + return true; + } + + void OnSyntaxError(User *u) + { + syntax_error(s_ChanServ, u, "SOP", CHAN_SOP_SYNTAX); + } +}; + +class CommandCSVOP : public XOPBase +{ + public: + CommandCSVOP() : XOPBase("VOP") + { + } + + CommandResult Execute(User *u, std::vector<std::string> ¶ms) + { + return this->DoXop(u, params, ACCESS_VOP, xop_msgs[XOP_VOP]); + } + + bool OnHelp(User *u, const std::string &subcommand) + { + notice_land(s_ChanServ, u, CHAN_HELP_VOP); + return true; + } + + void OnSyntaxError(User *u) + { + syntax_error(s_ChanServ, u, "VOP", CHAN_VOP_SYNTAX); + } +}; + +class CSXOP : public Module +{ + public: + CSXOP(const std::string &modname, const std::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetVersion("$Id$"); + this->SetType(CORE); + + this->AddCommand(CHANSERV, new CommandCSAOP(), MOD_UNIQUE); + if (ircd->halfop) + this->AddCommand(CHANSERV, new CommandCSHOP(), MOD_UNIQUE); + this->AddCommand(CHANSERV, new CommandCSSOP(), MOD_UNIQUE); + this->AddCommand(CHANSERV, new CommandCSVOP(), MOD_UNIQUE); + + this->SetChanHelp(myChanServHelp); + } +}; + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User *u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SOP); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_AOP); + if (ircd->halfop) + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_HOP); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_VOP); +} + +/* `last' is set to the last index this routine was called with + * `perm' is incremented whenever a permission-denied error occurs + */ +int xop_del(User *u, ChannelInfo *ci, ChanAccess *access, int *perm, int uacc, int xlev) +{ + char *nick = access->nc->display; + if (!access->in_use || access->level != xlev) + return 0; + if (!is_services_admin(u) && uacc <= access->level) + { + ++(*perm); + return 0; + } + access->nc = NULL; + access->in_use = 0; + send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, nick); + return 1; +} + +int xop_del_callback(User *u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *last = va_arg(args, int *); + int *perm = va_arg(args, int *); + int uacc = va_arg(args, int); + int xlev = va_arg(args, int); + + if (num < 1 || num > ci->accesscount) + return 0; + *last = num; + + return xop_del(u, ci, &ci->access[num - 1], perm, uacc, xlev); +} + + +int xop_list(User *u, int index, ChannelInfo *ci, int *sent_header, int xlev, int xmsg) +{ + ChanAccess *access = &ci->access[index]; + + if (!access->in_use || access->level != xlev) + return 0; + + if (!*sent_header) + { + notice_lang(s_ChanServ, u, xmsg, ci->name); + *sent_header = 1; + } + + notice_lang(s_ChanServ, u, CHAN_XOP_LIST_FORMAT, index + 1, access->nc->display); + return 1; +} + +int xop_list_callback(User *u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *sent_header = va_arg(args, int *); + int xlev = va_arg(args, int); + int xmsg = va_arg(args, int); + + if (num < 1 || num > ci->accesscount) + return 0; + + return xop_list(u, num - 1, ci, sent_header, xlev, xmsg); } MODULE_INIT("cs_xop", CSXOP) |