]> jfr.im git - irc/quakenet/newserv.git/blame - request/request_block.c
Cleanup.
[irc/quakenet/newserv.git] / request / request_block.c
CommitLineData
25b7d0fa
P
1#include <stdio.h>
2#include <string.h>
3#include "../irc/irc.h"
4#include "../lib/irc_string.h"
5#include "request_block.h"
6
7/* array of blocks */
8array rqblocks;
9
10/* our anti-flood nick extension */
11int rqnext;
12
13/* are we currently loading blocks? */
14int rq_loading;
15
16void rqhook_lostnick(int hook, void *arg);
17
18void rq_initblocks(void) {
19 array_init(&rqblocks, sizeof(rq_block));
20 array_setlim1(&rqblocks, 5);
21 array_setlim2(&rqblocks, 20);
22
23 rq_loading = 0;
24
25 rq_loadblocks();
26
27 rq_addblock("#qnet*", "Reserved for QuakeNet use only.", "request", 0, 0);
28 rq_addblock("#help*", "Reserved for QuakeNet use only.", "request", 0, 0);
29
30 registerhook(HOOK_NICK_LOSTNICK, &rqhook_lostnick);
31
32 rqnext = registernickext("request");
33}
34
35void rq_finiblocks(void) {
36 int i;
37 rq_block block;
38 nick *nip;
39
40 for (i = 0; i < rqblocks.cursi; i++) {
41 block = ((rq_block*)rqblocks.content)[i];
42
43 freesstring(block.pattern);
44 freesstring(block.reason);
45 freesstring(block.creator);
46 }
47
48 array_free(&rqblocks);
49
50 for (i=0; i<NICKHASHSIZE; i++)
51 for (nip=nicktable[i]; nip; nip=nip->next)
52 free(nip->exts[rqnext]);
53
54 deregisterhook(HOOK_NICK_LOSTNICK, &rqhook_lostnick);
55
56 releasenickext(rqnext);
57}
58
59void rqhook_lostnick(int hook, void *arg) {
60 nick *np = (nick*)arg;
61
62 free(np->exts[rqnext]);
63}
64
65int rq_isspam(nick *np) {
66 rq_flood *lf;
67
68 if (np->exts[rqnext] == NULL) {
69 np->exts[rqnext] = lf = (rq_flood*)malloc(sizeof(rq_flood));
70
71 lf->count = 1;
72 lf->created = getnettime();
73 lf->expire = 0;
74
75 return 0;
76 } else {
77 lf = np->exts[rqnext];
78
79 lf->count -= (getnettime() - lf->created) / (RQ_SPAMBLOCK / RQ_SPAMCOUNT);
80
81 if (lf->count < 0)
82 lf->count = 0;
83
84 if (lf->count > RQ_SPAMCOUNT && lf->expire > getnettime()) {
85 return 1;
86 } else {
87 lf->count++;
88
89 if (lf->count > RQ_SPAMCOUNT) {
90 lf->expire = getnettime() + RQ_SPAMBLOCK;
91
92 rq_addblock(np->authname, "Flooding the request system.", "request", 0, getnettime() + 3600);
93
94 return 1;
95 }
96
97 return 0;
98 }
99 }
100}
101
102time_t rq_blocktime(nick *np) {
103 if (np->exts[rqnext] == NULL)
104 return 0;
105 else
106 return ((rq_flood*)np->exts[rqnext])->expire - getnettime();
107}
108
109rq_block *rq_findblock(const char *pattern) {
110 int i;
111 rq_block block;
112
113 for (i = rqblocks.cursi - 1; i >= 0; i--) {
114 block = ((rq_block*)rqblocks.content)[i];
115
116 if (match2strings(block.pattern->content, pattern)) {
117 if (block.expires != 0 && block.expires < getnettime())
118 rq_removeblock(block.pattern->content);
119 else
120 return &(((rq_block*)rqblocks.content)[i]);
121 }
122 }
123
124 return NULL;
125}
126
127void rq_addblock(const char *pattern, const char *reason, const char *creator, time_t created, time_t expires) {
128 int slot;
129 rq_block *block;
130
131 if (rq_findblock(pattern) != NULL)
132 return;
133
134 slot = array_getfreeslot(&rqblocks);
135
136 block = &(((rq_block*)rqblocks.content)[slot]);
137
138 block->pattern = getsstring(pattern, CHANNELLEN);
139 block->reason = getsstring(reason, RQ_BLOCKLEN);
140 block->creator = getsstring(creator, ACCOUNTLEN);
141 block->created = created == 0 ? getnettime() : created;
142 block->expires = expires;
143
144 rq_saveblocks();
145}
146
147int rq_removeblock(const char *pattern) {
148 int i;
149 rq_block block;
150
151 for (i = 0; i < rqblocks.cursi; i++) {
152 block = ((rq_block*)rqblocks.content)[i];
153
154 if (ircd_strcmp(block.pattern->content, pattern) == 0) {
155 freesstring(block.pattern);
156 freesstring(block.reason);
157 freesstring(block.creator);
158
159 array_delslot(&rqblocks, i);
160
161 rq_saveblocks();
162
163 return 1;
164 }
165 }
166
167 return 0;
168}
169
170/* pattern reason creator created expires */
171int rq_parseline(char *line) {
172 char pattern[CHANNELLEN+1];
173 char reason[RQ_BLOCKLEN+1];
174 char creator[ACCOUNTLEN+1];
175 time_t created, expires;
176
177 if (sscanf(line, "%s %s %lu %lu %[^\n]", pattern, creator, &created, &expires, reason) < 2) /* \n won't be there anyway, but %s won't return the whole string */
178 return 0; /* invalid block */
179
180 /* tell rq_addblock that it should not save the blocks to disk this time */
181 rq_loading = 1;
182 rq_addblock(pattern, reason, creator, created, expires);
183 rq_loading = 0;
184
185 return 1;
186}
187
188int rq_loadblocks(void) {
189 char line[4096];
190 FILE *rqdata;
191 int count;
192
193 rqdata = fopen(RQ_BLOCKFILE, "r");
194
195 if (rqdata == NULL)
196 return 0;
197
198 count = 0;
199
200 while (!feof(rqdata)) {
201 if (fgets(line, sizeof(line), rqdata) == NULL)
202 break;
203
204 if (line[strlen(line) - 1] == '\n')
205 line[strlen(line) - 1] = '\0';
206
207 if (line[strlen(line) - 1] == '\r')
208 line[strlen(line) - 1] = '\0';
209
210 if (line[0] != '\0') {
211 if (rq_parseline(line))
212 count++;
213 }
214 }
215
216 fclose(rqdata);
217
218 return count;
219}
220
221int rq_saveblocks(void) {
222 FILE *rqdata;
223 int i, count = 0;
224
225 /* don't save the blocks if we're currently loading them from the disk */
226 if (rq_loading)
227 return 0;
228
229 rqdata = fopen(RQ_BLOCKFILE, "w");
230
231 if (rqdata == NULL)
232 return 0;
233
234 rq_block block;
235
236 for (i = 0; i < rqblocks.cursi; i++) {
237 block = ((rq_block*)rqblocks.content)[i];
238
239 fprintf(rqdata, "%s %s %lu %lu %s\n", block.pattern->content, block.creator->content, block.created, block.expires, block.reason->content);
240 }
241
242 fclose(rqdata);
243
244 return count;
245}