From 91ccda4f8cbf78c0c27180bc59be3ea2458a761e Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sat, 1 Feb 2020 02:10:33 +0000 Subject: [PATCH] Fix invite-notify and move it to an extension The existing approach to invite-notify is deeply flawed--it currently notifies only the target user's server, and that can't be fixed without sending notifies for invites that end up not happening. I'm resolving this by broadcasting a second message, INVITED, from the target user's server. I'm also pulling it out into an extension while I'm at it--invite notifies reveal new information, so I don't think they should be mandatory. --- extensions/Makefile.am | 1 + extensions/invite_notify.c | 74 ++++++++++++++++++++++++++++++++++++++ modules/m_invite.c | 31 +++++----------- 3 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 extensions/invite_notify.c diff --git a/extensions/Makefile.am b/extensions/Makefile.am index bbdee94c..e4460d1c 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -35,6 +35,7 @@ extension_LTLIBRARIES = \ force_user_invis.la \ helpops.la \ hurt.la \ + invite_notify.la \ ip_cloaking.la \ ip_cloaking_old.la \ ip_cloaking_3.0.la \ diff --git a/extensions/invite_notify.c b/extensions/invite_notify.c new file mode 100644 index 00000000..bc7c84f7 --- /dev/null +++ b/extensions/invite_notify.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include + +static const char inv_notify_desc[] = "Notifies channel on /invite and provides the invite-notify client capability"; + +static void hook_invite(void *); +static void m_invited(struct MsgBuf *, struct Client *, struct Client *, int, const char **); +static unsigned int CAP_INVITE_NOTIFY; + +mapi_hfn_list_av1 inv_notify_hfnlist[] = { + { "invite", hook_invite }, + { NULL, NULL } +}; + +struct Message invited_msgtab = { + "INVITED", 0, 0, 0, 0, + {mg_ignore, mg_ignore, mg_ignore, mg_ignore, {m_invited, 4}, mg_ignore} +}; + +mapi_cap_list_av2 inv_notify_caplist[] = { + { MAPI_CAP_CLIENT, "invite-notify", NULL, &CAP_INVITE_NOTIFY }, + { 0, NULL, NULL, NULL } +}; + +mapi_clist_av1 inv_notify_clist[] = { &invited_msgtab, NULL }; + +static void +invite_notify(struct Client *source, struct Client *target, struct Channel *channel) +{ + sendto_channel_local_with_capability(source, CHFL_CHANOP, 0, CAP_INVITE_NOTIFY, channel, + ":%s NOTICE %s :%s is inviting %s to %s.", + me.name, channel->chname, source->name, target->name, channel->chname); + sendto_channel_local_with_capability(source, CHFL_CHANOP, CAP_INVITE_NOTIFY, 0, channel, + ":%s!%s@%s INVITE %s %s", source->name, source->username, + source->host, target->name, channel->chname); +} + +static void +hook_invite(void *data_) +{ + hook_data_channel_approval *data = data_; + + if (data->approved) + /* Don't notify if another hook is rejecting the invite. + * This won't work if the other hook is after us... but really, it's + * the thought that counts. + */ + return; + + sendto_server(NULL, NULL, CAP_TS6 | CAP_ENCAP, 0, "ENCAP * INVITED %s %s %s", + use_id(data->client), use_id(data->target), + data->chptr->chname); + invite_notify(data->client, data->target, data->chptr); +} + +static void +m_invited(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char **parv) +{ + struct Client *inviter = find_person(parv[1]); + struct Client *target = find_person(parv[2]); + struct Channel *chptr = find_channel(parv[3]); + + if (inviter == NULL || target == NULL || chptr == NULL) + return; + + invite_notify(inviter, target, chptr); +} + +DECLARE_MODULE_AV2("invite_notify", NULL, NULL, inv_notify_clist, NULL, inv_notify_hfnlist, inv_notify_caplist, NULL, inv_notify_desc); diff --git a/modules/m_invite.c b/modules/m_invite.c index 044c72f5..ae7e6d23 100644 --- a/modules/m_invite.c +++ b/modules/m_invite.c @@ -38,10 +38,9 @@ #include "packet.h" #include "tgchange.h" -static const char invite_desc[] = "Provides facilities for invite and related notifications"; +static const char invite_desc[] = "Provides /invite"; static void m_invite(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static unsigned int CAP_INVITE_NOTIFY = 0; struct Message invite_msgtab = { "INVITE", 0, 0, 0, 0, @@ -58,12 +57,7 @@ mapi_hlist_av1 invite_hlist[] = { { NULL, NULL } }; -mapi_cap_list_av2 invite_cap_list[] = { - { MAPI_CAP_CLIENT, "invite-notify", NULL, &CAP_INVITE_NOTIFY }, - { 0, NULL, NULL, NULL } -}; - -DECLARE_MODULE_AV2(invite, NULL, NULL, invite_clist, invite_hlist, NULL, invite_cap_list, NULL, invite_desc); +DECLARE_MODULE_AV2(invite, NULL, NULL, invite_clist, invite_hlist, NULL, NULL, NULL, invite_desc); static bool add_invite(struct Channel *, struct Client *); @@ -255,22 +249,13 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source target_p->name, chptr->chname); if(store_invite) - { - if (!add_invite(chptr, target_p)) - return; - - sendto_channel_local_with_capability(source_p, CHFL_CHANOP, 0, CAP_INVITE_NOTIFY, chptr, - ":%s NOTICE %s :%s is inviting %s to %s.", - me.name, chptr->chname, source_p->name, target_p->name, chptr->chname); - sendto_channel_local_with_capability(source_p, CHFL_CHANOP, CAP_INVITE_NOTIFY, 0, chptr, - ":%s!%s@%s INVITE %s %s", source_p->name, source_p->username, - source_p->host, target_p->name, chptr->chname); - } + add_invite(chptr, target_p); + } + else if (target_p->from != client_p) + { + sendto_one_prefix(target_p, source_p, "INVITE", "%s %lu", + chptr->chname, (unsigned long) chptr->channelts); } - - sendto_server(source_p, chptr, CAP_TS6, 0, ":%s INVITE %s %s %lu", - use_id(source_p), use_id(target_p), - chptr->chname, (unsigned long) chptr->channelts); } /* add_invite()