diff --git a/src/api-usermode.c b/src/api-usermode.c index 078984002..76e5b8464 100644 --- a/src/api-usermode.c +++ b/src/api-usermode.c @@ -56,12 +56,15 @@ long SNO_OPER = 0L; long AllUmodes; /* All umodes */ long SendUmodes; /* All umodes which are sent to other servers (global umodes) */ +Umode *umode_letter_to_handler[256]; + /* Forward declarations */ int umode_hidle_allow(Client *client, int what); static void unload_usermode_commit(Umode *m); void umode_init(void) { + memset(umode_letter_to_handler, 0, sizeof(umode_letter_to_handler)); /* Some built-in modes */ UmodeAdd(NULL, 'i', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_INVISIBLE); UmodeAdd(NULL, 'o', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_OPER); @@ -81,8 +84,14 @@ void make_umodestr(void) char *p = umodestring; for (um=usermodes; um; um = um->next) + { if (um->letter) + { *p++ = um->letter; + if (!um->unloaded) + umode_letter_to_handler[um->letter] = um; + } + } *p = '\0'; } @@ -116,6 +125,8 @@ void usermode_add_sorted(Umode *n) { Umode *m; + umode_letter_to_handler[n->letter] = n; + if (usermodes == NULL) { usermodes = n; @@ -207,6 +218,8 @@ Umode *UmodeAdd(Module *module, char ch, int global, int unset_on_deoper, int (* um->letter = ch; um->mode = l; usermode_add_sorted(um); + } else { + umode_letter_to_handler[um->letter] = um; } um->letter = ch; @@ -318,9 +331,10 @@ static void unload_usermode_commit(Umode *um) } /* Then unload the mode */ + umode_letter_to_handler[um->letter] = NULL; DelListItem(um, usermodes); safe_free(um); - make_umodestr(); + make_umodestr(); // this sets umode_letter_to_handler[] properly if a newly loaded module took our handle over } void unload_all_unused_umodes(void) @@ -382,9 +396,18 @@ long find_user_mode(char letter) { Umode *um; +#ifndef DEBUGMODE + return umode_letter_to_handler[letter]; +#else + /* In debug mode we check for umode_letter_to_handler[] mismatch with list */ for (um = usermodes; um; um = um->next) if ((um->letter == letter) && !um->unloaded) + { + if (umode_letter_to_handler[letter] != um) + abort(); return um->mode; + } +#endif return 0; } diff --git a/src/send.c b/src/send.c index f84dd7245..634751f11 100644 --- a/src/send.c +++ b/src/send.c @@ -522,6 +522,10 @@ void sendto_channel(Channel *channel, Client *from, Client *skip, char member_modes_ext[64]; LineCache *cache; char check_invisible = 0; + long UMODE_CTCP; + + if (sendflags & SKIP_CTCP) + UMODE_CTCP = find_user_mode('T'); if (member_modes) { @@ -544,8 +548,8 @@ void sendto_channel(Channel *channel, Client *from, Client *skip, /* Don't send to deaf clients (unless 'senddeaf' is set) */ if (IsDeaf(acptr) && (sendflags & SKIP_DEAF)) continue; - /* Don't send to NOCTCP clients */ - if (has_user_mode(acptr, 'T') && (sendflags & SKIP_CTCP)) + /* Don't send to NOCTCP clients (umode +T) */ + if ((sendflags & SKIP_CTCP) && (acptr->umodes & UMODE_CTCP)) continue; /* Sender ('from') is invisible for 'acptr' and we were asked to CHECK_INVISIBLE */ if (check_invisible && !check_channel_access_member(lp, "hoaq") && (from != acptr))