diff --git a/include/send.h b/include/send.h index 57d6501c..4985b460 100644 --- a/include/send.h +++ b/include/send.h @@ -59,6 +59,7 @@ extern void sendto_channel_opmod(struct Client *one, struct Client *source_p, const char *text); extern void sendto_channel_local(struct Client *, int type, struct Channel *, const char *, ...) AFP(4, 5); +extern void sendto_channel_local_priv(struct Client *, int type, const char *priv, struct Channel *, const char *, ...) AFP(5, 6); extern void sendto_channel_local_butone(struct Client *, int type, struct Channel *, const char *, ...) AFP(4, 5); extern void sendto_channel_local_with_capability(struct Client *, int type, int caps, int negcaps, struct Channel *, const char *, ...) AFP(6, 7); diff --git a/ircd/chmode.c b/ircd/chmode.c index 9cbc7e8d..cfc38e9b 100644 --- a/ircd/chmode.c +++ b/ircd/chmode.c @@ -1742,7 +1742,13 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, for(j = 0; j < 3; j++) { - flags = flags_list[j]; + int send_flags = flags = flags_list[j]; + const char *priv = ""; + if (flags == ONLY_OPERS) + { + send_flags = ALL_MEMBERS; + priv = "auspex:cmodes"; + } cur_len = mlen; mbuf = modebuf + mlen; pbuf = parabuf; @@ -1775,8 +1781,8 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, *mbuf = '\0'; if(cur_len > mlen) - sendto_channel_local(IsServer(source_p) ? fakesource_p : source_p, - flags, chptr, "%s %s", modebuf, parabuf); + sendto_channel_local_priv(IsServer(source_p) ? fakesource_p : source_p, + send_flags, priv, chptr, "%s %s", modebuf, parabuf); else continue; @@ -1812,8 +1818,8 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, *mbuf = '\0'; if(cur_len > mlen) - sendto_channel_local(IsServer(source_p) ? fakesource_p : source_p, - flags, chptr, "%s %s", modebuf, parabuf); + sendto_channel_local_priv(IsServer(source_p) ? fakesource_p : source_p, + send_flags, priv, chptr, "%s %s", modebuf, parabuf); } /* only propagate modes originating locally, or if we're hubbing */ diff --git a/ircd/send.c b/ircd/send.c index d2a92d16..4205276c 100644 --- a/ircd/send.c +++ b/ircd/send.c @@ -675,6 +675,62 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p, msgbuf_cache_free(&msgbuf_cache); } +/* _sendto_channel_local + * + * inputs - source, flags to send to, privs to send to, channel to send to, va_args + * outputs - message to local channel members + * side effects - + */ +void +_sendto_channel_local(struct Client *source_p, int type, const char *priv, struct Channel *chptr, const char *pattern, va_list *args) +{ + struct membership *msptr; + struct Client *target_p; + rb_dlink_node *ptr; + rb_dlink_node *next_ptr; + struct MsgBuf msgbuf; + struct MsgBuf_cache msgbuf_cache; + rb_strf_t strings = { .format = pattern, .format_args = args, .next = NULL }; + + build_msgbuf_tags(&msgbuf, source_p); + + msgbuf_cache_init(&msgbuf_cache, &msgbuf, &strings); + + RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head) + { + msptr = ptr->data; + target_p = msptr->client_p; + + if (IsIOError(target_p)) + continue; + + if (type && ((msptr->flags & type) == 0)) + continue; + + if (priv != NULL && !HasPrivilege(target_p, priv)) + continue; + + _send_linebuf(target_p, msgbuf_cache_get(&msgbuf_cache, CLIENT_CAPS_ONLY(target_p))); + } + + msgbuf_cache_free(&msgbuf_cache); +} + +/* sendto_channel_local_priv() + * + * inputs - source, flags to send to, privs to send to, channel to send to, va_args + * outputs - message to local channel members + * side effects - + */ +void +sendto_channel_local_priv(struct Client *source_p, int type, const char *priv, struct Channel *chptr, const char *pattern, ...) +{ + va_list args; + va_start(args, pattern); + _sendto_channel_local(source_p, type, priv, chptr, pattern, &args); + va_end(args); +} + /* sendto_channel_local() * * inputs - source, flags to send to, channel to send to, va_args @@ -685,40 +741,9 @@ void sendto_channel_local(struct Client *source_p, int type, struct Channel *chptr, const char *pattern, ...) { va_list args; - struct membership *msptr; - struct Client *target_p; - rb_dlink_node *ptr; - rb_dlink_node *next_ptr; - struct MsgBuf msgbuf; - struct MsgBuf_cache msgbuf_cache; - rb_strf_t strings = { .format = pattern, .format_args = &args, .next = NULL }; - - build_msgbuf_tags(&msgbuf, source_p); - va_start(args, pattern); - msgbuf_cache_init(&msgbuf_cache, &msgbuf, &strings); + _sendto_channel_local(source_p, type, NULL, chptr, pattern, &args); va_end(args); - - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head) - { - msptr = ptr->data; - target_p = msptr->client_p; - - if(IsIOError(target_p)) - continue; - - if(type == ONLY_OPERS) - { - if (!IsOper(target_p)) - continue; - } - else if(type && ((msptr->flags & type) == 0)) - continue; - - _send_linebuf(target_p, msgbuf_cache_get(&msgbuf_cache, CLIENT_CAPS_ONLY(target_p))); - } - - msgbuf_cache_free(&msgbuf_cache); } /*