]>
Commit | Line | Data |
---|---|---|
1 | #include <string.h> | |
2 | #include "../core/schedule.h" | |
3 | #include "../control/control.h" | |
4 | #include "../lib/irc_string.h" | |
5 | #include "../localuser/localuserchannel.h" | |
6 | #include "../lib/version.h" | |
7 | ||
8 | MODULE_VERSION(""); | |
9 | ||
10 | static int ib_nickext; | |
11 | ||
12 | typedef struct ibnick { | |
13 | time_t timeout; | |
14 | void *sched; | |
15 | } ibnick; | |
16 | ||
17 | static void ib_clear_ext(void *arg) { | |
18 | nick *np = arg; | |
19 | ||
20 | if (!np->exts[ib_nickext]) | |
21 | return; | |
22 | ||
23 | free(np->exts[ib_nickext]); | |
24 | np->exts[ib_nickext] = NULL; | |
25 | } | |
26 | ||
27 | static void ib_hook_newnick(int hooknum, void *arg) { | |
28 | nick *np = arg; | |
29 | np->exts[ib_nickext] = NULL; | |
30 | } | |
31 | ||
32 | static void ib_hook_lostnick(int hooknum, void *arg) { | |
33 | nick *np = arg; | |
34 | ibnick *inp = np->exts[ib_nickext]; | |
35 | ||
36 | if (!inp) | |
37 | return; | |
38 | ||
39 | deleteschedule(inp->sched, ib_clear_ext, np); | |
40 | free(np->exts[ib_nickext]); | |
41 | } | |
42 | ||
43 | static void ib_hook_modechange(int hooknum, void *arg) { | |
44 | void **arglist=(void **)arg; | |
45 | channel *cp=(channel *)arglist[0]; | |
46 | nick *np=(nick *)arglist[1]; | |
47 | long changeflags=(long)arglist[2]; | |
48 | chanban *cbp; | |
49 | const char *p; | |
50 | int colons, colonsnext; | |
51 | modechanges changes; | |
52 | ibnick *inp; | |
53 | char *mask, *pos; | |
54 | int slot, i; | |
55 | array bans; | |
56 | ||
57 | if (!(changeflags & MODECHANGE_BANS)) | |
58 | return; | |
59 | ||
60 | inp = np->exts[ib_nickext]; | |
61 | ||
62 | /* Ignore the mode change if the same user has recently | |
63 | * set/unset a channel ban. */ | |
64 | if (inp && inp->timeout > time(NULL)) | |
65 | return; | |
66 | ||
67 | if (inp) { | |
68 | deleteschedule(inp->sched, ib_clear_ext, np); | |
69 | free(inp); | |
70 | np->exts[ib_nickext] = NULL; | |
71 | } | |
72 | ||
73 | array_init(&bans, 512); | |
74 | ||
75 | for (cbp = cp->bans; cbp; cbp = cbp->next) { | |
76 | if (!cbp->host) | |
77 | continue; | |
78 | ||
79 | colons = 0; | |
80 | colonsnext = 0; | |
81 | ||
82 | for (p = cbp->host->content; *p; p++) { | |
83 | if (*p == ':') { | |
84 | colons++; | |
85 | ||
86 | if (*(p + 1) == ':') | |
87 | colonsnext = 1; | |
88 | } | |
89 | } | |
90 | ||
91 | if (colons - colonsnext >= 8) { | |
92 | slot = array_getfreeslot(&bans); | |
93 | mask = ((char *)bans.content) + slot * 512; | |
94 | strncpy(mask, bantostring(cbp), 512); | |
95 | } | |
96 | } | |
97 | ||
98 | if (bans.cursi > 0) { | |
99 | localsetmodeinit(&changes, cp, NULL); | |
100 | ||
101 | for (i = 0; i < bans.cursi; i++) { | |
102 | mask = ((char *)bans.content) + i * 512; | |
103 | ||
104 | pos = strchr(mask, '@'); | |
105 | ||
106 | if (!pos) | |
107 | continue; /* This should never happen. */ | |
108 | ||
109 | pos++; /* Skip over the @ sign. */ | |
110 | ||
111 | for (; *pos; pos++) { | |
112 | if (*pos != ':') { | |
113 | *pos = '?'; | |
114 | break; | |
115 | } | |
116 | } | |
117 | ||
118 | localdosetmode_ban(&changes, mask, MCB_ADD); | |
119 | } | |
120 | ||
121 | localsetmodeflush(&changes, 1); | |
122 | ||
123 | /* Ignore the user for a short amount of time. If it's a bot | |
124 | * it'll probably try re-setting the ban immediately. */ | |
125 | inp = malloc(sizeof(ibnick)); | |
126 | inp->timeout = time(NULL) + 15; | |
127 | inp->sched = scheduleoneshot(inp->timeout + 1, ib_clear_ext, np); | |
128 | np->exts[ib_nickext] = inp; | |
129 | } | |
130 | ||
131 | array_free(&bans); | |
132 | } | |
133 | ||
134 | void _init() { | |
135 | registerhook(HOOK_NICK_NEWNICK, &ib_hook_newnick); | |
136 | registerhook(HOOK_NICK_LOSTNICK, &ib_hook_lostnick); | |
137 | registerhook(HOOK_CHANNEL_MODECHANGE, &ib_hook_modechange); | |
138 | ||
139 | ib_nickext = registernickext("invalidbans"); | |
140 | } | |
141 | ||
142 | void _fini () { | |
143 | deregisterhook(HOOK_NICK_NEWNICK, &ib_hook_newnick); | |
144 | deregisterhook(HOOK_NICK_LOSTNICK, &ib_hook_lostnick); | |
145 | deregisterhook(HOOK_CHANNEL_MODECHANGE, &ib_hook_modechange); | |
146 | ||
147 | releasenickext(ib_nickext); | |
148 | } | |
149 |