]> jfr.im git - solanum.git/blame - extensions/override.c
Use get_channel_access() for KICK/TOPIC.
[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);
d3076881 27static void hack_can_join(void *data);
429cf1b7
AC
28
29mapi_hfn_list_av1 override_hfnlist[] = {
30 { "umode_changed", (hookfn) check_umode_change },
31 { "get_channel_access", (hookfn) hack_channel_access },
d3076881 32 { "can_join", (hookfn) hack_can_join },
429cf1b7
AC
33 { NULL, NULL }
34};
35
36#define IsOperOverride(x) (HasPrivilege((x), "oper:override"))
37
38struct OverrideSession {
39 rb_dlink_node node;
40
41 struct Client *client;
42 time_t deadline;
43};
44
45rb_dlink_list overriding_opers = { NULL, NULL, 0 };
46
47static void
48update_session_deadline(struct Client *source_p, struct OverrideSession *session_p)
49{
50 if (session_p == NULL)
51 {
52 rb_dlink_node *n;
53
54 RB_DLINK_FOREACH(n, overriding_opers.head)
55 {
56 struct OverrideSession *s = n->data;
57
58 if (s->client == source_p)
59 {
60 session_p = s;
61 break;
62 }
63 }
64 }
65
66 if (session_p == NULL)
67 {
68 session_p = rb_malloc(sizeof(struct OverrideSession));
69 session_p->client = source_p;
70 }
71
72 session_p->deadline = rb_current_time() + 1800;
73
74 rb_dlinkDelete(&session_p->node, &overriding_opers);
75 rb_dlinkAdd(session_p, &session_p->node, &overriding_opers);
76}
77
78static void
79expire_override_deadlines(void *unused)
80{
81 rb_dlink_node *n, *tn;
82
83 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
84 {
85 struct OverrideSession *session_p = n->data;
86
87 if (session_p->deadline > rb_current_time())
88 break;
89 else if (session_p->deadline < rb_current_time())
90 {
91 const char *parv[4] = {session_p->client->name, session_p->client->name, "-p", NULL};
92 user_mode(session_p->client, session_p->client, 3, parv);
93 }
94 }
95}
96
97static void
98check_umode_change(void *vdata)
99{
100 hook_data_umode_changed *data = (hook_data_umode_changed *)vdata;
101 struct Client *source_p = data->client;
102
103 if (!MyClient(source_p))
104 return;
105
106 /* didn't change +p umode, we don't need to do anything */
107 if (!((data->oldumodes ^ source_p->umodes) & user_modes['p']))
108 return;
109
110 if (!IsOperOverride(source_p))
111 {
112 source_p->umodes &= ~user_modes['p'];
113 return;
114 }
115
116 if (source_p->umodes & user_modes['p'])
117 {
118 update_session_deadline(source_p, NULL);
119
120 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has enabled oper-override (+p)",
121 get_oper_name(source_p));
122 }
123 else if (!(source_p->umodes & user_modes['p']))
124 {
125 rb_dlink_node *n, *tn;
126
127 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
128 {
129 struct OverrideSession *session_p = n->data;
130
131 if (session_p->client != source_p)
132 continue;
133
134 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has disabled oper-override (+p)",
135 get_oper_name(session_p->client));
136
137 rb_dlinkDelete(n, &overriding_opers);
138 rb_free(session_p);
139 }
140 }
141}
142
143static void
144hack_channel_access(void *vdata)
145{
146 hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
147
148 if (data->approved == CHFL_CHANOP)
149 return;
150
151 if (data->client->umodes & user_modes['p'])
152 {
153 update_session_deadline(data->client, NULL);
154 data->approved = CHFL_CHANOP;
155
156 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (modehacking)",
157 get_oper_name(data->client), data->chptr->chname);
158 }
159}
160
d3076881
AC
161static void
162hack_can_join(void *vdata)
163{
164 hook_data_channel *data = (hook_data_channel *) vdata;
165
166 if (data->approved == 0)
167 return;
168
169 if (data->client->umodes & user_modes['p'])
170 {
171 update_session_deadline(data->client, NULL);
172 data->approved = 0;
173
174 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (banwalking)",
175 get_oper_name(data->client), data->chptr->chname);
176 }
177}
178
429cf1b7
AC
179struct ev_entry *expire_override_deadlines_ev = NULL;
180
181static int
182_modinit(void)
183{
184 /* add the usermode to the available slot */
185 user_modes['p'] = find_umode_slot();
186 construct_umodebuf();
187
188 expire_override_deadlines_ev = rb_event_add("expire_override_deadlines", expire_override_deadlines, NULL, 60);
189
190 return 0;
191}
192
193static void
194_moddeinit(void)
195{
196 /* disable the umode and remove it from the available list */
197 user_modes['p'] = 0;
198 construct_umodebuf();
199
200 rb_event_delete(expire_override_deadlines_ev);
201}
202
203DECLARE_MODULE_AV1(override, _modinit, _moddeinit, NULL, NULL,
204 override_hfnlist, "$Revision: 3526 $");