]> jfr.im git - solanum.git/blame - extensions/override.c
Add oper-override (modehacking only) as a module.
[solanum.git] / extensions / override.c
CommitLineData
429cf1b7
AC
1/*
2 * oper-override for charybdis.
3 *
4 * adds usermode +p and has a timer event that is iterated over to disable
5 * usermode +p after a while...
6 *
7 * you need to have oper:override permission on the opers you want to be
8 * able to use this extension.
9 */
10
11#include "stdinc.h"
12#include "modules.h"
13#include "hook.h"
14#include "client.h"
15#include "ircd.h"
16#include "send.h"
17#include "hash.h"
18#include "s_conf.h"
19#include "s_user.h"
20#include "s_serv.h"
21#include "numeric.h"
22#include "privilege.h"
23#include "s_newconf.h"
24
25static void check_umode_change(void *data);
26static void hack_channel_access(void *data);
27
28mapi_hfn_list_av1 override_hfnlist[] = {
29 { "umode_changed", (hookfn) check_umode_change },
30 { "get_channel_access", (hookfn) hack_channel_access },
31 { NULL, NULL }
32};
33
34#define IsOperOverride(x) (HasPrivilege((x), "oper:override"))
35
36struct OverrideSession {
37 rb_dlink_node node;
38
39 struct Client *client;
40 time_t deadline;
41};
42
43rb_dlink_list overriding_opers = { NULL, NULL, 0 };
44
45static void
46update_session_deadline(struct Client *source_p, struct OverrideSession *session_p)
47{
48 if (session_p == NULL)
49 {
50 rb_dlink_node *n;
51
52 RB_DLINK_FOREACH(n, overriding_opers.head)
53 {
54 struct OverrideSession *s = n->data;
55
56 if (s->client == source_p)
57 {
58 session_p = s;
59 break;
60 }
61 }
62 }
63
64 if (session_p == NULL)
65 {
66 session_p = rb_malloc(sizeof(struct OverrideSession));
67 session_p->client = source_p;
68 }
69
70 session_p->deadline = rb_current_time() + 1800;
71
72 rb_dlinkDelete(&session_p->node, &overriding_opers);
73 rb_dlinkAdd(session_p, &session_p->node, &overriding_opers);
74}
75
76static void
77expire_override_deadlines(void *unused)
78{
79 rb_dlink_node *n, *tn;
80
81 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
82 {
83 struct OverrideSession *session_p = n->data;
84
85 if (session_p->deadline > rb_current_time())
86 break;
87 else if (session_p->deadline < rb_current_time())
88 {
89 const char *parv[4] = {session_p->client->name, session_p->client->name, "-p", NULL};
90 user_mode(session_p->client, session_p->client, 3, parv);
91 }
92 }
93}
94
95static void
96check_umode_change(void *vdata)
97{
98 hook_data_umode_changed *data = (hook_data_umode_changed *)vdata;
99 struct Client *source_p = data->client;
100
101 if (!MyClient(source_p))
102 return;
103
104 /* didn't change +p umode, we don't need to do anything */
105 if (!((data->oldumodes ^ source_p->umodes) & user_modes['p']))
106 return;
107
108 if (!IsOperOverride(source_p))
109 {
110 source_p->umodes &= ~user_modes['p'];
111 return;
112 }
113
114 if (source_p->umodes & user_modes['p'])
115 {
116 update_session_deadline(source_p, NULL);
117
118 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has enabled oper-override (+p)",
119 get_oper_name(source_p));
120 }
121 else if (!(source_p->umodes & user_modes['p']))
122 {
123 rb_dlink_node *n, *tn;
124
125 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
126 {
127 struct OverrideSession *session_p = n->data;
128
129 if (session_p->client != source_p)
130 continue;
131
132 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has disabled oper-override (+p)",
133 get_oper_name(session_p->client));
134
135 rb_dlinkDelete(n, &overriding_opers);
136 rb_free(session_p);
137 }
138 }
139}
140
141static void
142hack_channel_access(void *vdata)
143{
144 hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
145
146 if (data->approved == CHFL_CHANOP)
147 return;
148
149 if (data->client->umodes & user_modes['p'])
150 {
151 update_session_deadline(data->client, NULL);
152 data->approved = CHFL_CHANOP;
153
154 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (modehacking)",
155 get_oper_name(data->client), data->chptr->chname);
156 }
157}
158
159struct ev_entry *expire_override_deadlines_ev = NULL;
160
161static int
162_modinit(void)
163{
164 /* add the usermode to the available slot */
165 user_modes['p'] = find_umode_slot();
166 construct_umodebuf();
167
168 expire_override_deadlines_ev = rb_event_add("expire_override_deadlines", expire_override_deadlines, NULL, 60);
169
170 return 0;
171}
172
173static void
174_moddeinit(void)
175{
176 /* disable the umode and remove it from the available list */
177 user_modes['p'] = 0;
178 construct_umodebuf();
179
180 rb_event_delete(expire_override_deadlines_ev);
181}
182
183DECLARE_MODULE_AV1(override, _modinit, _moddeinit, NULL, NULL,
184 override_hfnlist, "$Revision: 3526 $");