From 5e413b1372dabb744426dc20b08da3cc28b39a79 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Wed, 27 May 2020 00:16:22 +0100 Subject: [PATCH] Use linear channel list comparisons --- extensions/hide_uncommon_channels.c | 7 +-- include/hook.h | 11 ++++- ircd/tgchange.c | 27 +++++++++--- modules/m_whois.c | 68 ++++++++++++++++++++++------- 4 files changed, 86 insertions(+), 27 deletions(-) diff --git a/extensions/hide_uncommon_channels.c b/extensions/hide_uncommon_channels.c index ff1d0cb6..586dc360 100644 --- a/extensions/hide_uncommon_channels.c +++ b/extensions/hide_uncommon_channels.c @@ -14,7 +14,7 @@ static const char hide_desc[] = "Hides channel memberships not shared"; -static void h_huc_doing_whois_channel_visibility(hook_data_client *); +static void h_huc_doing_whois_channel_visibility(void *); mapi_hfn_list_av1 huc_hfnlist[] = { { "doing_whois_channel_visibility", (hookfn) h_huc_doing_whois_channel_visibility }, @@ -24,7 +24,8 @@ mapi_hfn_list_av1 huc_hfnlist[] = { DECLARE_MODULE_AV2(hide_uncommon_channels, NULL, NULL, NULL, NULL, huc_hfnlist, NULL, NULL, hide_desc); static void -h_huc_doing_whois_channel_visibility(hook_data_client *hdata) +h_huc_doing_whois_channel_visibility(void *data_) { - hdata->approved = ((PubChannel(hdata->chptr) && !IsInvisible(hdata->target)) || IsMember((hdata->client), (hdata->chptr))); + hook_data_channel_visibility *data = data_; + data->approved = data->approved && (!IsInvisible(data->targms->client_p) || data->clientms != NULL); } diff --git a/include/hook.h b/include/hook.h index ddcf6b6c..f3a2b88f 100644 --- a/include/hook.h +++ b/include/hook.h @@ -79,8 +79,6 @@ typedef struct { struct Client *client; struct Client *target; - struct Channel *chptr; - int approved; } hook_data_client; typedef struct @@ -109,6 +107,15 @@ typedef struct const char *error; } hook_data_channel_approval; +typedef struct +{ + struct Client *client; + struct Channel *chptr; + struct membership *clientms; + struct membership *targms; + int approved; +} hook_data_channel_visibility; + typedef struct { struct Client *client; diff --git a/ircd/tgchange.c b/ircd/tgchange.c index b9f427bd..c8e595aa 100644 --- a/ircd/tgchange.c +++ b/ircd/tgchange.c @@ -38,14 +38,29 @@ static int add_hashed_target(struct Client *source_p, uint32_t hashv); struct Channel * find_allowing_channel(struct Client *source_p, struct Client *target_p) { - rb_dlink_node *ptr; - struct membership *msptr; + rb_dlink_node *ps = source_p->user->channel.head; + rb_dlink_node *pt = target_p->user->channel.head; - RB_DLINK_FOREACH(ptr, source_p->user->channel.head) + while (ps && pt) { - msptr = ptr->data; - if (is_chanop_voiced(msptr) && IsMember(target_p, msptr->chptr)) - return msptr->chptr; + struct membership *ms = ps->data; + struct membership *mt = pt->data; + int d; + if (ms->chptr == mt->chptr) + { + if (is_chanop_voiced(ms)) + return ms->chptr; + ps = ps->next; + pt = pt->next; + continue; + } + d = irccmp(ms->chptr->chname, mt->chptr->chname); + if (d < 0) + ps = ps->next; + else if (d > 0) + pt = pt->next; + else + assert("different channels can't have equal names" && false); } return NULL; } diff --git a/modules/m_whois.c b/modules/m_whois.c index 6fd1bcfc..d07f0fc6 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -225,8 +225,6 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) { char buf[BUFSIZE]; rb_dlink_node *ptr; - struct membership *msptr; - struct Channel *chptr; int cur_len = 0; int mlen; char *t; @@ -269,19 +267,57 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) if (!IsService(target_p)) { - RB_DLINK_FOREACH(ptr, target_p->user->channel.head) + hook_data_channel_visibility hdata_vis; + rb_dlink_node *ps = source_p->user->channel.head; + rb_dlink_node *pt = target_p->user->channel.head; + + hdata_vis.client = source_p; + + while (pt) { - msptr = ptr->data; - chptr = msptr->chptr; - - hdata.chptr = chptr; - - hdata.approved = ShowChannel(source_p, chptr); - call_hook(doing_whois_channel_visibility_hook, &hdata); - - if(hdata.approved || operspy) + struct membership *mt = pt->data; + int dir = 0; + if (ps != NULL) { - if((cur_len + strlen(chptr->chname) + 3) > (BUFSIZE - 5)) + struct membership *ms = ps->data; + if (ms->chptr == mt->chptr) + { + ps = ps->next; + pt = pt->next; + hdata_vis.chptr = mt->chptr; + hdata_vis.clientms = ms; + hdata_vis.targms = mt; + hdata_vis.approved = 1; + dir = 0; + } + else + { + dir = irccmp(ms->chptr->chname, mt->chptr->chname); + } + } + else + { + dir = 1; + } + if (dir < 0) + { + ps = ps->next; + continue; + } + else if (dir > 0) + { + pt = pt->next; + hdata_vis.chptr = mt->chptr; + hdata_vis.clientms = NULL; + hdata_vis.targms = mt; + hdata_vis.approved = PubChannel(mt->chptr); + } + + call_hook(doing_whois_channel_visibility_hook, &hdata_vis); + + if(hdata_vis.approved || operspy) + { + if((cur_len + strlen(mt->chptr->chname) + 3) > (BUFSIZE - 5)) { sendto_one(source_p, "%s", buf); cur_len = mlen + extra_space; @@ -289,9 +325,9 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) } tlen = sprintf(t, "%s%s%s ", - hdata.approved ? "" : "!", - find_channel_status(msptr, 1), - chptr->chname); + hdata_vis.approved ? "" : "!", + find_channel_status(mt, 1), + mt->chptr->chname); t += tlen; cur_len += tlen; }