From 6c639159b0e1acb5bc0d2e9e9d439218c4190028 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sat, 3 Aug 2019 05:13:49 +0100 Subject: [PATCH 1/3] helpops: fix umode handling construct_umodebuf() can change the char->flag mapping (to restore an orphaned mode). I don't love the use of a fake constant, so I think the cleanest solution here is just to index user_modes with a macro for the umode letter. --- extensions/helpops.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/extensions/helpops.c b/extensions/helpops.c index 6198a460..5633420e 100644 --- a/extensions/helpops.c +++ b/extensions/helpops.c @@ -39,7 +39,7 @@ mapi_hfn_list_av1 helpops_hfnlist[] = { { NULL, NULL } }; -static int UMODE_HELPOPS = 0; +#define UMODECHAR_HELPOPS 'H' struct Message dehelper_msgtab = { "DEHELPER", 0, 0, 0, 0, @@ -92,7 +92,7 @@ do_dehelper(struct Client *source_p, struct Client *target_p) { const char *fakeparv[4]; - if(!(target_p->umodes & UMODE_HELPOPS)) + if(!(target_p->umodes & user_modes[UMODECHAR_HELPOPS])) return; sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using DEHELPER on %s", @@ -108,8 +108,7 @@ do_dehelper(struct Client *source_p, struct Client *target_p) static int _modinit(void) { - /* add the usermode to the available slot */ - user_modes['H'] = UMODE_HELPOPS = find_umode_slot(); + user_modes[UMODECHAR_HELPOPS] = find_umode_slot(); construct_umodebuf(); return 0; @@ -118,8 +117,7 @@ _modinit(void) static void _moddeinit(void) { - /* disable the umode and remove it from the available list */ - user_modes['H'] = UMODE_HELPOPS = 0; + user_modes[UMODECHAR_HELPOPS] = 0; construct_umodebuf(); } @@ -172,7 +170,7 @@ helper_delete(struct Client *client_p) static void h_hdl_new_remote_user(struct Client *client_p) { - if (client_p->umodes & UMODE_HELPOPS) + if (client_p->umodes & user_modes[UMODECHAR_HELPOPS]) helper_add(client_p); } @@ -181,7 +179,7 @@ recurse_client_exit(struct Client *client_p) { if (IsPerson(client_p)) { - if (client_p->umodes & UMODE_HELPOPS) + if (client_p->umodes & user_modes[UMODECHAR_HELPOPS]) helper_delete(client_p); } else if (IsServer(client_p)) @@ -208,21 +206,21 @@ h_hdl_umode_changed(hook_data_umode_changed *hdata) struct Client *source_p = hdata->client; /* didn't change +H umode, we don't need to do anything */ - if (!((hdata->oldumodes ^ source_p->umodes) & UMODE_HELPOPS)) + if (!((hdata->oldumodes ^ source_p->umodes) & user_modes[UMODECHAR_HELPOPS])) return; - if (source_p->umodes & UMODE_HELPOPS) + if (source_p->umodes & user_modes[UMODECHAR_HELPOPS]) { if (MyClient(source_p) && !HasPrivilege(source_p, "usermode:helpops")) { - source_p->umodes &= ~UMODE_HELPOPS; + source_p->umodes &= ~user_modes[UMODECHAR_HELPOPS]; sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "usermode:helpops"); return; } helper_add(source_p); } - else if (!(source_p->umodes & UMODE_HELPOPS)) + else if (!(source_p->umodes & user_modes[UMODECHAR_HELPOPS])) helper_delete(source_p); } @@ -232,7 +230,7 @@ h_hdl_whois(hook_data_client *hdata) struct Client *source_p = hdata->client; struct Client *target_p = hdata->target; - if ((target_p->umodes & UMODE_HELPOPS) && EmptyString(target_p->user->away)) + if ((target_p->umodes & user_modes[UMODECHAR_HELPOPS]) && EmptyString(target_p->user->away)) { sendto_one_numeric(source_p, RPL_WHOISHELPOP, form_str(RPL_WHOISHELPOP), target_p->name); } From 0c5dd86cfcd1c018ebf69ce515e94b5fbbccb5ac Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sat, 3 Aug 2019 05:17:35 +0100 Subject: [PATCH 2/3] helpops: handle the helper list properly on reload Free the whole list on unload rather than leaking it, and initialise it to the list of people with +H on load. --- extensions/helpops.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/extensions/helpops.c b/extensions/helpops.c index 5633420e..1fb3b423 100644 --- a/extensions/helpops.c +++ b/extensions/helpops.c @@ -108,17 +108,31 @@ do_dehelper(struct Client *source_p, struct Client *target_p) static int _modinit(void) { + rb_dlink_node *ptr; + user_modes[UMODECHAR_HELPOPS] = find_umode_slot(); construct_umodebuf(); + RB_DLINK_FOREACH (ptr, global_client_list.head) + { + struct Client *client_p = ptr->data; + if (IsPerson(client_p) && (client_p->umodes & user_modes[UMODECHAR_HELPOPS])) + helper_add(client_p); + } + return 0; } static void _moddeinit(void) { + rb_dlink_node *n, *tn; + user_modes[UMODECHAR_HELPOPS] = 0; construct_umodebuf(); + + RB_DLINK_FOREACH_SAFE(n, tn, helper_list.head) + rb_dlinkDestroy(n, &helper_list); } static void From 5339043003420437a5f0840bd5298e2cc09a6a45 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sat, 3 Aug 2019 06:41:09 +0100 Subject: [PATCH 3/3] helpops: remove +H if usermode:helpops is lost --- extensions/helpops.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/extensions/helpops.c b/extensions/helpops.c index 1fb3b423..95932744 100644 --- a/extensions/helpops.c +++ b/extensions/helpops.c @@ -220,8 +220,7 @@ h_hdl_umode_changed(hook_data_umode_changed *hdata) struct Client *source_p = hdata->client; /* didn't change +H umode, we don't need to do anything */ - if (!((hdata->oldumodes ^ source_p->umodes) & user_modes[UMODECHAR_HELPOPS])) - return; + bool changed = (hdata->oldumodes ^ source_p->umodes) & user_modes[UMODECHAR_HELPOPS]; if (source_p->umodes & user_modes[UMODECHAR_HELPOPS]) { @@ -229,13 +228,19 @@ h_hdl_umode_changed(hook_data_umode_changed *hdata) { source_p->umodes &= ~user_modes[UMODECHAR_HELPOPS]; sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "usermode:helpops"); + /* they didn't ask for +H so we must be removing it */ + if (!changed) + helper_delete(source_p); return; } - helper_add(source_p); + if (changed) + helper_add(source_p); } - else if (!(source_p->umodes & user_modes[UMODECHAR_HELPOPS])) + else if (changed) + { helper_delete(source_p); + } } static void