diff options
Diffstat (limited to 'src/core/cs_access.c')
-rw-r--r-- | src/core/cs_access.c | 872 |
1 files changed, 436 insertions, 436 deletions
diff --git a/src/core/cs_access.c b/src/core/cs_access.c index 31e8df133..b70192c02 100644 --- a/src/core/cs_access.c +++ b/src/core/cs_access.c @@ -51,72 +51,72 @@ class CSAccess : public Module **/ void myChanServHelp(User * u) { - notice_lang(s_ChanServ, u, CHAN_HELP_CMD_ACCESS); - notice_lang(s_ChanServ, u, CHAN_HELP_CMD_LEVELS); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_ACCESS); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_LEVELS); } static int access_del(User * u, ChannelInfo *ci, ChanAccess * access, int *perm, int uacc) { char *nick; - if (!access->in_use) - return 0; - if (!is_services_admin(u) && uacc <= access->level) { - (*perm)++; - return 0; - } - nick = access->nc->display; - access->nc = NULL; - access->in_use = 0; - send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, nick); - return 1; + if (!access->in_use) + return 0; + if (!is_services_admin(u) && uacc <= access->level) { + (*perm)++; + return 0; + } + nick = access->nc->display; + access->nc = NULL; + access->in_use = 0; + send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, nick); + return 1; } static int access_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); - if (num < 1 || num > ci->accesscount) - return 0; - *last = num; - return access_del(u, ci, &ci->access[num - 1], perm, uacc); + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *last = va_arg(args, int *); + int *perm = va_arg(args, int *); + int uacc = va_arg(args, int); + if (num < 1 || num > ci->accesscount) + return 0; + *last = num; + return access_del(u, ci, &ci->access[num - 1], perm, uacc); } static int access_list(User * u, int index, ChannelInfo * ci, - int *sent_header) + int *sent_header) { - ChanAccess *access = &ci->access[index]; - const char *xop; - - if (!access->in_use) - return 0; - - if (!*sent_header) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name); - *sent_header = 1; - } - - if (ci->flags & CI_XOP) { - xop = get_xop_level(access->level); - notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_XOP_FORMAT, index + 1, - xop, access->nc->display); - } else { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_AXS_FORMAT, index + 1, - access->level, access->nc->display); - } - return 1; + ChanAccess *access = &ci->access[index]; + const char *xop; + + if (!access->in_use) + return 0; + + if (!*sent_header) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name); + *sent_header = 1; + } + + if (ci->flags & CI_XOP) { + xop = get_xop_level(access->level); + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_XOP_FORMAT, index + 1, + xop, access->nc->display); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_AXS_FORMAT, index + 1, + access->level, access->nc->display); + } + return 1; } static int access_list_callback(User * u, int num, va_list args) { - ChannelInfo *ci = va_arg(args, ChannelInfo *); - int *sent_header = va_arg(args, int *); - if (num < 1 || num > ci->accesscount) - return 0; - return access_list(u, num - 1, ci, sent_header); + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *sent_header = va_arg(args, int *); + if (num < 1 || num > ci->accesscount) + return 0; + return access_list(u, num - 1, ci, sent_header); } @@ -127,402 +127,402 @@ static int access_list_callback(User * u, int num, va_list args) **/ int do_access(User * u) { - char *chan = strtok(NULL, " "); - char *cmd = strtok(NULL, " "); - char *nick = strtok(NULL, " "); - char *s = strtok(NULL, " "); - char event_access[BUFSIZE]; - - ChannelInfo *ci; - NickAlias *na = NULL; - NickCore *nc; - ChanAccess *access; - - int i; - int level = 0, ulev; - int is_list = (cmd && stricmp(cmd, "LIST") == 0); - int is_servadmin = is_services_admin(u); - - /* If LIST, we don't *require* any parameters, but we can take any. - * If DEL, we require a nick and no level. - * Else (ADD), we require a level (which implies a nick). */ - if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : - (stricmp(cmd, "DEL") == 0) ? (!nick || s) : !s)) { - syntax_error(s_ChanServ, u, "ACCESS", CHAN_ACCESS_SYNTAX); - } 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); - /* We still allow LIST in xOP mode, but not others */ - } else if ((ci->flags & CI_XOP) && !is_list) { + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + char *s = strtok(NULL, " "); + char event_access[BUFSIZE]; + + ChannelInfo *ci; + NickAlias *na = NULL; + NickCore *nc; + ChanAccess *access; + + int i; + int level = 0, ulev; + int is_list = (cmd && stricmp(cmd, "LIST") == 0); + int is_servadmin = is_services_admin(u); + + /* If LIST, we don't *require* any parameters, but we can take any. + * If DEL, we require a nick and no level. + * Else (ADD), we require a level (which implies a nick). */ + if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : + (stricmp(cmd, "DEL") == 0) ? (!nick || s) : !s)) { + syntax_error(s_ChanServ, u, "ACCESS", CHAN_ACCESS_SYNTAX); + } 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); + /* We still allow LIST in xOP mode, but not others */ + } else if ((ci->flags & CI_XOP) && !is_list) { if (ircd->halfop) - notice_lang(s_ChanServ, u, CHAN_ACCESS_XOP_HOP, s_ChanServ); + notice_lang(s_ChanServ, u, CHAN_ACCESS_XOP_HOP, s_ChanServ); else - notice_lang(s_ChanServ, u, CHAN_ACCESS_XOP, s_ChanServ); - } else if (((is_list && !check_access(u, ci, CA_ACCESS_LIST)) - || (!is_list && !check_access(u, ci, CA_ACCESS_CHANGE))) - && !is_servadmin) { - notice_lang(s_ChanServ, u, ACCESS_DENIED); - } else if (stricmp(cmd, "ADD") == 0) { - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); - return MOD_CONT; - } - - level = atoi(s); - ulev = get_access(u, ci); - - if (!is_servadmin && level >= ulev) { - notice_lang(s_ChanServ, u, PERMISSION_DENIED); - return MOD_CONT; - } - - if (level == 0) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_NONZERO); - return MOD_CONT; - } else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_RANGE, - ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); - return MOD_CONT; - } - - na = findnick(nick); - if (!na) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_NICKS_ONLY); - return MOD_CONT; - } - if (na->status & NS_VERBOTEN) { - notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, nick); - return MOD_CONT; - } - - nc = na->nc; - for (access = ci->access, i = 0; i < ci->accesscount; - access++, i++) { - if (access->nc == nc) { - /* Don't allow lowering from a level >= ulev */ - if (!is_servadmin && access->level >= ulev) { - notice_lang(s_ChanServ, u, PERMISSION_DENIED); - return MOD_CONT; - } - if (access->level == level) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_UNCHANGED, - access->nc->display, chan, level); - return MOD_CONT; - } - access->level = level; - snprintf(event_access, BUFSIZE, "%d", access->level); - send_event(EVENT_ACCESS_CHANGE, 4, ci->name, u->nick, - na->nick, event_access); - alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, access->level, na->nick, nc->display, ci->name); - notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_CHANGED, - access->nc->display, chan, level); - return MOD_CONT; - } - } - - /* 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 = - (ChanAccess *)srealloc(ci->access, - sizeof(ChanAccess) * ci->accesscount); - } else { - notice_lang(s_ChanServ, u, CHAN_ACCESS_REACHED_LIMIT, - CSAccessMax); - return MOD_CONT; - } - - access = &ci->access[i]; - access->nc = nc; - access->in_use = 1; - access->level = level; - access->last_seen = 0; - - snprintf(event_access, BUFSIZE, "%d", access->level); - send_event(EVENT_ACCESS_ADD, 4, ci->name, u->nick, na->nick, - event_access); - alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, access->level, na->nick, nc->display, ci->name); - notice_lang(s_ChanServ, u, CHAN_ACCESS_ADDED, nc->display, - ci->name, access->level); - } else if (stricmp(cmd, "DEL") == 0) { - int deleted, a, b; - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); - return MOD_CONT; - } - - if (ci->accesscount == 0) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); - 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)) { - int count, last = -1, perm = 0; - deleted = process_numlist(nick, &count, access_del_callback, u, - ci, &last, &perm, get_access(u, ci)); - if (!deleted) { - if (perm) { - notice_lang(s_ChanServ, u, PERMISSION_DENIED); - } else if (count == 1) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_SUCH_ENTRY, - last, ci->name); - } else { - notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_MATCH, - ci->name); - } - } else if (deleted == 1) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED_ONE, - ci->name); - } else { - notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED_SEVERAL, - deleted, ci->name); - } - } else { - 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) - break; - } - if (i == ci->accesscount) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_NOT_FOUND, nick, - chan); - return MOD_CONT; - } - access = &ci->access[i]; - if (!is_servadmin && get_access(u, ci) <= access->level) { - deleted = 0; - notice_lang(s_ChanServ, u, PERMISSION_DENIED); - } else { - notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED, - access->nc->display, ci->name); - alog("%s: %s!%s@%s (level %d) deleted access of %s (group %s) on %s", s_ChanServ, u->nick, u->username, u->host, get_access(u, ci), na->nick, access->nc->display, chan); - access->nc = NULL; - access->in_use = 0; - deleted = 1; - } - } - - if (deleted) { - /* Reordering - DrStein */ - 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) { - 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[b].nc = NULL; - ci->access[b].in_use = 0; - break; - } - } - } - } - - /* 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--) { - if (ci->access[i].in_use == 1) - break; - - ci->accesscount--; - } - ci->access = - (ChanAccess *)srealloc(ci->access,sizeof(ChanAccess) * ci->accesscount); - - /* We don't know the nick if someone used numbers, so we trigger the event without - * nick param. We just do this once, even if someone enters a range. -Certus */ - if (na) - send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, na->nick); - else - send_event(EVENT_ACCESS_DEL, 2, ci->name, u->nick); - } - } else if (stricmp(cmd, "LIST") == 0) { - int sent_header = 0; - - if (ci->accesscount == 0) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); - return MOD_CONT; - } - if (nick && strspn(nick, "1234567890,-") == strlen(nick)) { - process_numlist(nick, NULL, access_list_callback, u, ci, - &sent_header); - } else { - for (i = 0; i < ci->accesscount; i++) { - if (nick && ci->access[i].nc - && !match_wild_nocase(nick, ci->access[i].nc->display)) - continue; - access_list(u, i, ci, &sent_header); - } - } - if (!sent_header) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan); - } else { - notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name); - } - } else if (stricmp(cmd, "CLEAR") == 0) { - - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); - return MOD_CONT; - } - - if (!is_servadmin && !is_founder(u, ci)) { - notice_lang(s_ChanServ, u, PERMISSION_DENIED); - return MOD_CONT; - } - - free(ci->access); - ci->access = NULL; - ci->accesscount = 0; - - send_event(EVENT_ACCESS_CLEAR, 2, ci->name, u->nick); - - notice_lang(s_ChanServ, u, CHAN_ACCESS_CLEAR, ci->name); - alog("%s: %s!%s@%s (level %d) cleared access list on %s", - s_ChanServ, u->nick, u->username, u->host, - get_access(u, ci), chan); - - } else { - syntax_error(s_ChanServ, u, "ACCESS", CHAN_ACCESS_SYNTAX); - } - return MOD_CONT; + notice_lang(s_ChanServ, u, CHAN_ACCESS_XOP, s_ChanServ); + } else if (((is_list && !check_access(u, ci, CA_ACCESS_LIST)) + || (!is_list && !check_access(u, ci, CA_ACCESS_CHANGE))) + && !is_servadmin) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (stricmp(cmd, "ADD") == 0) { + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + return MOD_CONT; + } + + level = atoi(s); + ulev = get_access(u, ci); + + if (!is_servadmin && level >= ulev) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (level == 0) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_NONZERO); + return MOD_CONT; + } else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_RANGE, + ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); + return MOD_CONT; + } + + na = findnick(nick); + if (!na) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NICKS_ONLY); + return MOD_CONT; + } + if (na->status & NS_VERBOTEN) { + notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + + nc = na->nc; + for (access = ci->access, i = 0; i < ci->accesscount; + access++, i++) { + if (access->nc == nc) { + /* Don't allow lowering from a level >= ulev */ + if (!is_servadmin && access->level >= ulev) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + if (access->level == level) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_UNCHANGED, + access->nc->display, chan, level); + return MOD_CONT; + } + access->level = level; + snprintf(event_access, BUFSIZE, "%d", access->level); + send_event(EVENT_ACCESS_CHANGE, 4, ci->name, u->nick, + na->nick, event_access); + alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, access->level, na->nick, nc->display, ci->name); + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_CHANGED, + access->nc->display, chan, level); + return MOD_CONT; + } + } + + /* 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 = + (ChanAccess *)srealloc(ci->access, + sizeof(ChanAccess) * ci->accesscount); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_REACHED_LIMIT, + CSAccessMax); + return MOD_CONT; + } + + access = &ci->access[i]; + access->nc = nc; + access->in_use = 1; + access->level = level; + access->last_seen = 0; + + snprintf(event_access, BUFSIZE, "%d", access->level); + send_event(EVENT_ACCESS_ADD, 4, ci->name, u->nick, na->nick, + event_access); + alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, access->level, na->nick, nc->display, ci->name); + notice_lang(s_ChanServ, u, CHAN_ACCESS_ADDED, nc->display, + ci->name, access->level); + } else if (stricmp(cmd, "DEL") == 0) { + int deleted, a, b; + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + return MOD_CONT; + } + + if (ci->accesscount == 0) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); + 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)) { + int count, last = -1, perm = 0; + deleted = process_numlist(nick, &count, access_del_callback, u, + ci, &last, &perm, get_access(u, ci)); + if (!deleted) { + if (perm) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else if (count == 1) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_SUCH_ENTRY, + last, ci->name); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_MATCH, + ci->name); + } + } else if (deleted == 1) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED_ONE, + ci->name); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED_SEVERAL, + deleted, ci->name); + } + } else { + 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) + break; + } + if (i == ci->accesscount) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NOT_FOUND, nick, + chan); + return MOD_CONT; + } + access = &ci->access[i]; + if (!is_servadmin && get_access(u, ci) <= access->level) { + deleted = 0; + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED, + access->nc->display, ci->name); + alog("%s: %s!%s@%s (level %d) deleted access of %s (group %s) on %s", s_ChanServ, u->nick, u->username, u->host, get_access(u, ci), na->nick, access->nc->display, chan); + access->nc = NULL; + access->in_use = 0; + deleted = 1; + } + } + + if (deleted) { + /* Reordering - DrStein */ + 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) { + 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[b].nc = NULL; + ci->access[b].in_use = 0; + break; + } + } + } + } + + /* 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--) { + if (ci->access[i].in_use == 1) + break; + + ci->accesscount--; + } + ci->access = + (ChanAccess *)srealloc(ci->access,sizeof(ChanAccess) * ci->accesscount); + + /* We don't know the nick if someone used numbers, so we trigger the event without + * nick param. We just do this once, even if someone enters a range. -Certus */ + if (na) + send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, na->nick); + else + send_event(EVENT_ACCESS_DEL, 2, ci->name, u->nick); + } + } else if (stricmp(cmd, "LIST") == 0) { + int sent_header = 0; + + if (ci->accesscount == 0) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); + return MOD_CONT; + } + if (nick && strspn(nick, "1234567890,-") == strlen(nick)) { + process_numlist(nick, NULL, access_list_callback, u, ci, + &sent_header); + } else { + for (i = 0; i < ci->accesscount; i++) { + if (nick && ci->access[i].nc + && !match_wild_nocase(nick, ci->access[i].nc->display)) + continue; + access_list(u, i, ci, &sent_header); + } + } + if (!sent_header) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name); + } + } else if (stricmp(cmd, "CLEAR") == 0) { + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + return MOD_CONT; + } + + if (!is_servadmin && !is_founder(u, ci)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + free(ci->access); + ci->access = NULL; + ci->accesscount = 0; + + send_event(EVENT_ACCESS_CLEAR, 2, ci->name, u->nick); + + notice_lang(s_ChanServ, u, CHAN_ACCESS_CLEAR, ci->name); + alog("%s: %s!%s@%s (level %d) cleared access list on %s", + s_ChanServ, u->nick, u->username, u->host, + get_access(u, ci), chan); + + } else { + syntax_error(s_ChanServ, u, "ACCESS", CHAN_ACCESS_SYNTAX); + } + return MOD_CONT; } int do_levels(User * u) { - char *chan = strtok(NULL, " "); - char *cmd = strtok(NULL, " "); - char *what = strtok(NULL, " "); - char *s = strtok(NULL, " "); - char *error; - - ChannelInfo *ci; - int level; - int i; - - /* If SET, we want two extra parameters; if DIS[ABLE] or FOUNDER, we want only - * one; else, we want none. - */ - if (!cmd - || ((stricmp(cmd, "SET") == 0) ? !s - : ((strnicmp(cmd, "DIS", 3) == 0)) ? (!what || s) : !!what)) { - syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); - } 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_LEVELS_XOP); - } else if (!is_founder(u, ci) && !is_services_admin(u)) { - notice_lang(s_ChanServ, u, ACCESS_DENIED); - } else if (stricmp(cmd, "SET") == 0) { - level = strtol(s, &error, 10); - - if (*error != '\0') { - syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); - return MOD_CONT; - } - - if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { - notice_lang(s_ChanServ, u, CHAN_LEVELS_RANGE, - ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); - return MOD_CONT; - } - - for (i = 0; levelinfo[i].what >= 0; i++) { - if (stricmp(levelinfo[i].name, what) == 0) { - ci->levels[levelinfo[i].what] = level; - - alog("%s: %s!%s@%s set level %s on channel %s to %d", - s_ChanServ, u->nick, u->username, u->host, - levelinfo[i].name, ci->name, level); - notice_lang(s_ChanServ, u, CHAN_LEVELS_CHANGED, - levelinfo[i].name, chan, level); - return MOD_CONT; - } - } - - notice_lang(s_ChanServ, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); - - } else if (stricmp(cmd, "DIS") == 0 || stricmp(cmd, "DISABLE") == 0) { - for (i = 0; levelinfo[i].what >= 0; i++) { - if (stricmp(levelinfo[i].name, what) == 0) { - ci->levels[levelinfo[i].what] = ACCESS_INVALID; - - alog("%s: %s!%s@%s disabled level %s on channel %s", - s_ChanServ, u->nick, u->username, u->host, - levelinfo[i].name, ci->name); - notice_lang(s_ChanServ, u, CHAN_LEVELS_DISABLED, - levelinfo[i].name, chan); - return MOD_CONT; - } - } - - notice_lang(s_ChanServ, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); - } else if (stricmp(cmd, "LIST") == 0) { - notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_HEADER, chan); - - if (!levelinfo_maxwidth) { - for (i = 0; levelinfo[i].what >= 0; i++) { - int len = strlen(levelinfo[i].name); - if (len > levelinfo_maxwidth) - levelinfo_maxwidth = len; - } - } - - for (i = 0; levelinfo[i].what >= 0; i++) { - int j = ci->levels[levelinfo[i].what]; - - if (j == ACCESS_INVALID) { - j = levelinfo[i].what; - - if (j == CA_AUTOOP || j == CA_AUTODEOP || j == CA_AUTOVOICE - || j == CA_NOJOIN) { - notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_DISABLED, - levelinfo_maxwidth, levelinfo[i].name); - } else { - notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_DISABLED, - levelinfo_maxwidth, levelinfo[i].name); - } - } else if (j == ACCESS_FOUNDER) { - notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_FOUNDER, - levelinfo_maxwidth, levelinfo[i].name); - } else { - notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_NORMAL, - levelinfo_maxwidth, levelinfo[i].name, j); - } - } - - } else if (stricmp(cmd, "RESET") == 0) { - reset_levels(ci); - - alog("%s: %s!%s@%s reset levels definitions on channel %s", - s_ChanServ, u->nick, u->username, u->host, ci->name); - notice_lang(s_ChanServ, u, CHAN_LEVELS_RESET, chan); - } else { - syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); - } - return MOD_CONT; + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *what = strtok(NULL, " "); + char *s = strtok(NULL, " "); + char *error; + + ChannelInfo *ci; + int level; + int i; + + /* If SET, we want two extra parameters; if DIS[ABLE] or FOUNDER, we want only + * one; else, we want none. + */ + if (!cmd + || ((stricmp(cmd, "SET") == 0) ? !s + : ((strnicmp(cmd, "DIS", 3) == 0)) ? (!what || s) : !!what)) { + syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); + } 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_LEVELS_XOP); + } else if (!is_founder(u, ci) && !is_services_admin(u)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (stricmp(cmd, "SET") == 0) { + level = strtol(s, &error, 10); + + if (*error != '\0') { + syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); + return MOD_CONT; + } + + if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_RANGE, + ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); + return MOD_CONT; + } + + for (i = 0; levelinfo[i].what >= 0; i++) { + if (stricmp(levelinfo[i].name, what) == 0) { + ci->levels[levelinfo[i].what] = level; + + alog("%s: %s!%s@%s set level %s on channel %s to %d", + s_ChanServ, u->nick, u->username, u->host, + levelinfo[i].name, ci->name, level); + notice_lang(s_ChanServ, u, CHAN_LEVELS_CHANGED, + levelinfo[i].name, chan, level); + return MOD_CONT; + } + } + + notice_lang(s_ChanServ, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); + + } else if (stricmp(cmd, "DIS") == 0 || stricmp(cmd, "DISABLE") == 0) { + for (i = 0; levelinfo[i].what >= 0; i++) { + if (stricmp(levelinfo[i].name, what) == 0) { + ci->levels[levelinfo[i].what] = ACCESS_INVALID; + + alog("%s: %s!%s@%s disabled level %s on channel %s", + s_ChanServ, u->nick, u->username, u->host, + levelinfo[i].name, ci->name); + notice_lang(s_ChanServ, u, CHAN_LEVELS_DISABLED, + levelinfo[i].name, chan); + return MOD_CONT; + } + } + + notice_lang(s_ChanServ, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); + } else if (stricmp(cmd, "LIST") == 0) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_HEADER, chan); + + if (!levelinfo_maxwidth) { + for (i = 0; levelinfo[i].what >= 0; i++) { + int len = strlen(levelinfo[i].name); + if (len > levelinfo_maxwidth) + levelinfo_maxwidth = len; + } + } + + for (i = 0; levelinfo[i].what >= 0; i++) { + int j = ci->levels[levelinfo[i].what]; + + if (j == ACCESS_INVALID) { + j = levelinfo[i].what; + + if (j == CA_AUTOOP || j == CA_AUTODEOP || j == CA_AUTOVOICE + || j == CA_NOJOIN) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_DISABLED, + levelinfo_maxwidth, levelinfo[i].name); + } else { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_DISABLED, + levelinfo_maxwidth, levelinfo[i].name); + } + } else if (j == ACCESS_FOUNDER) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_FOUNDER, + levelinfo_maxwidth, levelinfo[i].name); + } else { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_NORMAL, + levelinfo_maxwidth, levelinfo[i].name, j); + } + } + + } else if (stricmp(cmd, "RESET") == 0) { + reset_levels(ci); + + alog("%s: %s!%s@%s reset levels definitions on channel %s", + s_ChanServ, u->nick, u->username, u->host, ci->name); + notice_lang(s_ChanServ, u, CHAN_LEVELS_RESET, chan); + } else { + syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); + } + return MOD_CONT; } MODULE_INIT("cs_access", CSAccess) |