diff --git a/include/client.h b/include/client.h index 41ee5af..17e5a52 100644 --- a/include/client.h +++ b/include/client.h @@ -451,6 +451,8 @@ struct ListClient #define CLICAP_MULTI_PREFIX 0x0001 #define CLICAP_SASL 0x0002 +#define CLICAP_ACCOUNT_NOTIFY 0x0004 +#define CLICAP_EXTENDED_JOIN 0x0008 /* * flags macros. diff --git a/include/send.h b/include/send.h index ddb50cd..290f13a 100644 --- a/include/send.h +++ b/include/send.h @@ -62,8 +62,11 @@ extern void sendto_channel_opmod(struct Client *one, struct Client *source_p, extern void sendto_channel_local(int type, struct Channel *, const char *, ...) AFP(3, 4); extern void sendto_channel_local_butone(struct Client *, int type, struct Channel *, const char *, ...) AFP(4, 5); -extern void sendto_common_channels_local(struct Client *, const char *, ...) AFP(2, 3); -extern void sendto_common_channels_local_butone(struct Client *, const char *, ...) AFP(2, 3); + +extern void sendto_channel_local_with_capability(int type, int caps, int negcaps, struct Channel *, const char *, ...) AFP(5, 6); + +extern void sendto_common_channels_local(struct Client *, int cap, const char *, ...) AFP(3, 4); +extern void sendto_common_channels_local_butone(struct Client *, int cap, const char *, ...) AFP(3, 4); extern void sendto_match_butone(struct Client *, struct Client *, diff --git a/modules/core/m_nick.c b/modules/core/m_nick.c index 6251168..87b3c10 100644 --- a/modules/core/m_nick.c +++ b/modules/core/m_nick.c @@ -721,7 +721,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p, source_p->name, nick, source_p->username, source_p->host); /* send the nick change to the users channels */ - sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s", + sendto_common_channels_local(source_p, NOCAPS, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); /* send the nick change to servers.. */ @@ -782,7 +782,7 @@ change_remote_nick(struct Client *client_p, struct Client *source_p, monitor_signoff(source_p); } - sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s", + sendto_common_channels_local(source_p, NOCAPS, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); if(source_p->user) diff --git a/modules/m_cap.c b/modules/m_cap.c index acc3515..7bff1a6 100644 --- a/modules/m_cap.c +++ b/modules/m_cap.c @@ -67,8 +67,10 @@ static struct clicap int flags; int namelen; } clicap_list[] = { - _CLICAP("multi-prefix", CLICAP_MULTI_PREFIX, 0, 0), - _CLICAP("sasl", CLICAP_SASL, 0, 0) + _CLICAP("multi-prefix", CLICAP_MULTI_PREFIX, 0, 0), + _CLICAP("sasl", CLICAP_SASL, 0, 0), + _CLICAP("account-notify", CLICAP_ACCOUNT_NOTIFY, 0, 0), + _CLICAP("extended-join", CLICAP_EXTENDED_JOIN, 0, 0) }; #define CLICAP_LIST_LEN (sizeof(clicap_list) / sizeof(struct clicap)) diff --git a/modules/m_services.c b/modules/m_services.c index 42ea29d..ecee113 100644 --- a/modules/m_services.c +++ b/modules/m_services.c @@ -106,6 +106,10 @@ me_su(struct Client *client_p, struct Client *source_p, else rb_strlcpy(target_p->user->suser, parv[2], sizeof(target_p->user->suser)); + sendto_common_channels_local_butone(target_p, CLICAP_ACCOUNT_NOTIFY, ":%s!%s@%s ACCOUNT :%s", + target_p->name, target_p->username, target_p->host, + EmptyString(target_p->user->suser) ? "*" : target_p->user->suser); + invalidate_bancache_user(target_p); return 0; @@ -216,7 +220,7 @@ me_rsfnc(struct Client *client_p, struct Client *source_p, target_p->name, parv[2], target_p->username, target_p->host); - sendto_common_channels_local(target_p, ":%s!%s@%s NICK :%s", + sendto_common_channels_local(target_p, NOCAPS, ":%s!%s@%s NICK :%s", target_p->name, target_p->username, target_p->host, parv[2]); diff --git a/src/channel.c b/src/channel.c index 9075594..1aea425 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1722,7 +1722,7 @@ check_forward(struct Client *source_p, struct Channel *chptr, * * inputs - pointer to client doing join 0 * output - NONE - * side effects - Use has decided to join 0. This is legacy + * side effects - User has decided to join 0. This is legacy * from the days when channels were numbers not names. *sigh* */ void @@ -1999,9 +1999,14 @@ void user_join(struct Client * client_p, struct Client * source_p, const char * /* we send the user their join here, because we could have to * send a mode out next. */ - sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s", - source_p->name, - source_p->username, source_p->host, chptr->chname); + + sendto_channel_local_with_capability(ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN, chptr, ":%s!%s@%s JOIN %s", + source_p->name, source_p->username, source_p->host, chptr->chname); + + sendto_channel_local_with_capability(ALL_MEMBERS, CLICAP_EXTENDED_JOIN, NOCAPS, chptr, ":%s!%s@%s JOIN %s %s %ld :%s", + source_p->name, source_p->username, source_p->host, chptr->chname, + EmptyString(source_p->user->suser) ? "*" : source_p->user->suser, + source_p->tsinfo, source_p->info); /* its a new channel, set +nt and burst. */ if(flags & CHFL_CHANOP) diff --git a/src/client.c b/src/client.c index 9e8c737..f763b27 100644 --- a/src/client.c +++ b/src/client.c @@ -1148,7 +1148,7 @@ exit_generic_client(struct Client *client_p, struct Client *source_p, struct Cli /* get rid of any metadata the user may have */ user_metadata_clear(source_p); - sendto_common_channels_local(source_p, ":%s!%s@%s QUIT :%s", + sendto_common_channels_local(source_p, NOCAPS, ":%s!%s@%s QUIT :%s", source_p->name, source_p->username, source_p->host, comment); diff --git a/src/s_user.c b/src/s_user.c index 01691c4..fef0001 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -1530,7 +1530,7 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use vsnprintf(reason, 255, format, ap); va_end(ap); - sendto_common_channels_local_butone(target_p, ":%s!%s@%s QUIT :%s", + sendto_common_channels_local_butone(target_p, NOCAPS, ":%s!%s@%s QUIT :%s", target_p->name, target_p->username, target_p->host, reason); @@ -1586,7 +1586,7 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use } else if(changed_case) { - sendto_common_channels_local(target_p, ":%s!%s@%s NICK :%s", + sendto_common_channels_local(target_p, NOCAPS, ":%s!%s@%s NICK :%s", target_p->name, target_p->username, target_p->host, nick); } diff --git a/src/send.c b/src/send.c index e82acd9..3b62f11 100644 --- a/src/send.c +++ b/src/send.c @@ -702,18 +702,93 @@ sendto_channel_local_butone(struct Client *one, int type, struct Channel *chptr, rb_linebuf_donebuf(&linebuf); } +/* + * _sendto_channel_local_with_capability_butone() + * + * Shared implementation of sendto_channel_local_with_capability and sendto_channel_local_with_capability_butone + */ +static void +_sendto_channel_local_with_capability_butone(struct Client *one, int type, int caps, int negcaps, struct Channel *chptr, + const char *pattern, va_list * args) +{ + buf_head_t linebuf; + struct membership *msptr; + struct Client *target_p; + rb_dlink_node *ptr; + rb_dlink_node *next_ptr; + + rb_linebuf_newbuf(&linebuf); + rb_linebuf_putmsg(&linebuf, pattern, args, NULL); + + RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head) + { + msptr = ptr->data; + target_p = msptr->client_p; + + if (target_p == one) + continue; + + if(IsIOError(target_p) || + !IsCapable(target_p, caps) || + !NotCapable(target_p, negcaps)) + continue; + + if(type && ((msptr->flags & type) == 0)) + continue; + + _send_linebuf(target_p, &linebuf); + } + + rb_linebuf_donebuf(&linebuf); +} + +/* sendto_channel_local_with_capability() + * + * inputs - flags to send to, caps, negate caps, channel to send to, va_args + * outputs - message to local channel members + * side effects - + */ +void +sendto_channel_local_with_capability(int type, int caps, int negcaps, struct Channel *chptr, const char *pattern, ...) +{ + va_list args; + + va_start(args, pattern); + _sendto_channel_local_with_capability_butone(NULL, type, caps, negcaps, chptr, pattern, &args); + va_end(args); +} + + +/* sendto_channel_local_with_capability() + * + * inputs - flags to send to, caps, negate caps, channel to send to, va_args + * outputs - message to local channel members + * side effects - + */ +void +sendto_channel_local_with_capability_butone(struct Client *one, int type, int caps, int negcaps, struct Channel *chptr, + const char *pattern, ...) +{ + va_list args; + + va_start(args, pattern); + _sendto_channel_local_with_capability_butone(one, type, caps, negcaps, chptr, pattern, &args); + va_end(args); +} + /* * sendto_common_channels_local() * * inputs - pointer to client * - pattern to send + * - capability mask * output - NONE * side effects - Sends a message to all people on local server who are * in same channel with user. * used by m_nick.c and exit_one_client. */ void -sendto_common_channels_local(struct Client *user, const char *pattern, ...) +sendto_common_channels_local(struct Client *user, int cap, const char *pattern, ...) { va_list args; rb_dlink_node *ptr; @@ -744,7 +819,8 @@ sendto_common_channels_local(struct Client *user, const char *pattern, ...) target_p = msptr->client_p; if(IsIOError(target_p) || - target_p->serial == current_serial) + target_p->serial == current_serial || + !IsCapable(target_p, cap)) continue; target_p->serial = current_serial; @@ -766,12 +842,13 @@ sendto_common_channels_local(struct Client *user, const char *pattern, ...) * * inputs - pointer to client * - pattern to send + * - capability mask * output - NONE * side effects - Sends a message to all people on local server who are * in same channel with user, except for user itself. */ void -sendto_common_channels_local_butone(struct Client *user, const char *pattern, ...) +sendto_common_channels_local_butone(struct Client *user, int cap, const char *pattern, ...) { va_list args; rb_dlink_node *ptr; @@ -804,7 +881,8 @@ sendto_common_channels_local_butone(struct Client *user, const char *pattern, .. target_p = msptr->client_p; if(IsIOError(target_p) || - target_p->serial == current_serial) + target_p->serial == current_serial || + !IsCapable(target_p, cap)) continue; target_p->serial = current_serial;