X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/e47c4be18ccb033c6ddf548b6edd9f87df5d6175..8f0c3422e75189b7f39a7555ded278ab6027707b:/extensions/helpops.c diff --git a/extensions/helpops.c b/extensions/helpops.c index 465e363d..72d81290 100644 --- a/extensions/helpops.c +++ b/extensions/helpops.c @@ -22,6 +22,9 @@ static void h_hdl_new_remote_user(struct Client *client_p); static void h_hdl_client_exit(hook_data_client_exit *hdata); static void h_hdl_umode_changed(hook_data_umode_changed *hdata); static void h_hdl_whois(hook_data_client *hdata); +static void recurse_client_exit(struct Client *client_p); +static void helper_add(struct Client *client_p); +static void helper_delete(struct Client *client_p); static void mo_dehelper(struct MsgBuf *, struct Client *, struct Client *, int, const char **); static void me_dehelper(struct MsgBuf *, struct Client *, struct Client *, int, const char **); static void do_dehelper(struct Client *source_p, struct Client *target_p); @@ -36,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, @@ -50,9 +53,9 @@ mo_dehelper(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou { struct Client *target_p; - if (!IsOperAdmin(source_p)) + if (!HasPrivilege(source_p, "oper:dehelper")) { - sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); + sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "dehelper"); return; } @@ -88,8 +91,9 @@ static void do_dehelper(struct Client *source_p, struct Client *target_p) { const char *fakeparv[4]; + static const char minus_helpops[3] = {'-', UMODECHAR_HELPOPS, '\0'}; - 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", @@ -97,7 +101,7 @@ do_dehelper(struct Client *source_p, struct Client *target_p) sendto_one_notice(target_p, ":*** %s is using DEHELPER on you", source_p->name); fakeparv[0] = fakeparv[1] = target_p->name; - fakeparv[2] = "-H"; + fakeparv[2] = minus_helpops; fakeparv[3] = NULL; user_mode(target_p, target_p, 3, fakeparv); } @@ -105,19 +109,31 @@ 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(); + 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) { - /* disable the umode and remove it from the available list */ - user_modes['H'] = UMODE_HELPOPS = 0; + 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 @@ -151,57 +167,81 @@ h_hdl_stats_request(hook_data_int *hdata) hdata->result = 1; } +static void +helper_add(struct Client *client_p) +{ + if (rb_dlinkFind(client_p, &helper_list) != NULL) + return; + + rb_dlinkAddAlloc(client_p, &helper_list); +} + +static void +helper_delete(struct Client *client_p) +{ + rb_dlinkFindDestroy(client_p, &helper_list); +} + static void h_hdl_new_remote_user(struct Client *client_p) { - if (client_p->umodes & UMODE_HELPOPS) - rb_dlinkAddAlloc(client_p, &helper_list); + if (client_p->umodes & user_modes[UMODECHAR_HELPOPS]) + helper_add(client_p); } static void -h_hdl_client_exit(hook_data_client_exit *hdata) +recurse_client_exit(struct Client *client_p) { - if (IsPerson(hdata->target)) + if (IsPerson(client_p)) { - if (hdata->target->umodes & UMODE_HELPOPS) - rb_dlinkFindDestroy(hdata->target, &helper_list); + if (client_p->umodes & user_modes[UMODECHAR_HELPOPS]) + helper_delete(client_p); } - else if (IsServer(hdata->target)) + else if (IsServer(client_p)) { rb_dlink_node *nptr; - RB_DLINK_FOREACH(nptr, hdata->target->serv->users.head) - { - struct Client *client_p = nptr->data; + RB_DLINK_FOREACH(nptr, client_p->serv->users.head) + recurse_client_exit(nptr->data); - if (client_p->umodes & UMODE_HELPOPS) - rb_dlinkFindDestroy(client_p, &helper_list); - } + RB_DLINK_FOREACH(nptr, client_p->serv->servers.head) + recurse_client_exit(nptr->data); } } +static void +h_hdl_client_exit(hook_data_client_exit *hdata) +{ + recurse_client_exit(hdata->target); +} + static void 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)) - return; + /* didn't change +h umode, we don't need to do anything */ + bool changed = (hdata->oldumodes ^ source_p->umodes) & user_modes[UMODECHAR_HELPOPS]; - 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"); + /* they didn't ask for +h so we must be removing it */ + if (!changed) + helper_delete(source_p); return; } - rb_dlinkAddAlloc(source_p, &helper_list); + if (changed) + helper_add(source_p); + } + else if (changed) + { + helper_delete(source_p); } - else if (!(source_p->umodes & UMODE_HELPOPS)) - rb_dlinkFindDestroy(source_p, &helper_list); } static void @@ -210,7 +250,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); }