]>
jfr.im git - irc/quakenet/newserv.git/blob - newsearch/ns-gline.c
12 #include "../control/control.h"
13 #include "../irc/irc.h" /* irc_send() */
14 #include "../lib/irc_string.h" /* IPtostr(), longtoduration(), durationtolong() */
15 #include "../lib/strlfunc.h"
16 #include "../core/schedule.h"
17 #include "../glines/glines.h"
19 /* used for *_free functions that need to warn users of certain things
20 i.e. hitting too many users in a (kill) or (gline) - declared in newsearch.c */
21 extern nick
*senderNSExtern
;
22 static const char *defaultreason
= "You (%u) have been g-lined for violating our terms of service";
23 static int defaultmindelay
= 15;
24 static int defaultvariance
= 15;
26 void *gline_exe(searchCtx
*ctx
, struct searchNode
*thenode
, void *theinput
);
27 void gline_free(searchCtx
*ctx
, struct searchNode
*thenode
);
29 struct gline_localdata
{
31 unsigned int duration
;
33 char reason
[NSMAX_REASON_LEN
];
38 struct searchNode
*common_gline_parse(searchCtx
*ctx
, int argc
, char **argv
, int withdelay
) {
39 struct gline_localdata
*localdata
;
40 struct searchNode
*thenode
;
42 if (!(localdata
= (struct gline_localdata
*) malloc(sizeof(struct gline_localdata
)))) {
43 parseError
= "malloc: could not allocate memory for this search.";
47 if (ctx
->searchcmd
== reg_chansearch
)
48 localdata
->marker
= nextchanmarker();
49 else if (ctx
->searchcmd
== reg_nicksearch
)
50 localdata
->marker
= nextnickmarker();
51 else if (ctx
->searchcmd
== reg_whowassearch
)
52 localdata
->marker
= nextwhowasmarker();
55 parseError
= "gline: invalid search type";
59 /* default duration, default reason */
61 localdata
->duration
= NSGLINE_DURATION
;
62 strlcpy(localdata
->reason
, defaultreason
, sizeof(localdata
->reason
));
63 } else if(argc
> (withdelay
? 4 : 2)) {
65 parseError
= "gline: invalid number of arguments";
68 char *argzerop
, *reasonp
, *durationp
, *mindelayp
, *maxdelayp
;
69 struct searchNode
*durationsn
, *reasonsn
, *mindelaysn
, *maxdelaysn
, *argzerosn
;
71 if (!(argzerosn
=argtoconststr("gline", ctx
, argv
[0], &argzerop
))) {
77 durationp
= reasonp
= mindelayp
= maxdelayp
= NULL
;
78 durationsn
= reasonsn
= mindelaysn
= maxdelaysn
= NULL
;
80 /* if we have a space it's a reason */
81 if(strchr(argzerop
, ' ')) {
85 durationsn
= argzerosn
;
89 durationsn
= argzerosn
;
92 if (!(reasonsn
=argtoconststr("gline", ctx
, argv
[1], &reasonp
))) {
93 durationsn
->free(ctx
, durationsn
);
99 mindelayp
= maxdelayp
= NULL
;
100 mindelaysn
= maxdelaysn
= NULL
;
102 if (argc
> 2 && !(mindelaysn
=argtoconststr("gline", ctx
, argv
[2], &mindelayp
))) {
103 mindelaysn
->free(ctx
, mindelaysn
);
108 if (argc
> 3 && !(maxdelaysn
=argtoconststr("gline", ctx
, argv
[3], &maxdelayp
))) {
109 maxdelaysn
->free(ctx
, maxdelaysn
);
117 strlcpy(localdata
->reason
, defaultreason
, sizeof(localdata
->reason
));
119 strlcpy(localdata
->reason
, reasonp
, sizeof(localdata
->reason
));
120 reasonsn
->free(ctx
, reasonsn
);
124 localdata
->duration
= NSGLINE_DURATION
;
126 localdata
->duration
= durationtolong(durationp
);
127 durationsn
->free(ctx
, durationsn
);
129 if (localdata
->duration
== 0) {
130 parseError
= "gline duration invalid.";
138 localdata
->mindelay
= defaultmindelay
;
140 localdata
->mindelay
= durationtolong(mindelayp
);
141 mindelaysn
->free(ctx
, mindelaysn
);
143 if (localdata
->mindelay
== 0) {
144 parseError
= "gline mindelay invalid.";
151 localdata
->maxdelay
= localdata
->mindelay
+ defaultvariance
;
153 localdata
->maxdelay
= durationtolong(maxdelayp
);
154 maxdelaysn
->free(ctx
, maxdelaysn
);
156 if (localdata
->maxdelay
== 0) {
157 parseError
= "gline maxdelay invalid.";
163 localdata
->mindelay
= 0;
164 localdata
->maxdelay
= 0;
167 if (localdata
->mindelay
< 0 || localdata
->maxdelay
< localdata
->mindelay
) {
168 parseError
= "gline delay invalid.";
174 if (!(thenode
=(struct searchNode
*)malloc(sizeof (struct searchNode
)))) {
175 /* couldn't malloc() memory for thenode, so free localdata to avoid leakage */
176 parseError
= "malloc: could not allocate memory for this search.";
181 thenode
->returntype
= RETURNTYPE_BOOL
;
182 thenode
->localdata
= localdata
;
183 thenode
->exe
= gline_exe
;
184 thenode
->free
= gline_free
;
189 struct searchNode
*gline_parse(searchCtx
*ctx
, int argc
, char **argv
) {
190 return common_gline_parse(ctx
, argc
, argv
, 0);
193 struct searchNode
*delaygline_parse(searchCtx
*ctx
, int argc
, char **argv
) {
194 return common_gline_parse(ctx
, argc
, argv
, 1);
197 void *gline_exe(searchCtx
*ctx
, struct searchNode
*thenode
, void *theinput
) {
198 struct gline_localdata
*localdata
;
203 localdata
= thenode
->localdata
;
205 if (ctx
->searchcmd
== reg_chansearch
) {
206 cip
= (chanindex
*)theinput
;
207 cip
->marker
= localdata
->marker
;
208 if (cip
->channel
!= NULL
)
209 localdata
->count
+= cip
->channel
->users
->totalusers
;
212 np
= (nick
*)theinput
;
213 if (ctx
->searchcmd
== reg_nicksearch
)
214 np
->marker
= localdata
->marker
;
216 ww
= (whowas
*)np
->next
;
217 ww
->marker
= localdata
->marker
;
225 static int glineuser(glinebuf
*gbuf
, nick
*np
, struct gline_localdata
*localdata
, time_t ti
) {
227 if (!IsOper(np
) && !IsService(np
) && !IsXOper(np
)) {
228 nssnprintf(msgbuf
, sizeof(msgbuf
), localdata
->reason
, np
);
229 glinebufaddbynick(gbuf
, np
, 0, "newsearch", msgbuf
, getnettime() + localdata
->duration
, getnettime(), getnettime() + localdata
->duration
);
236 static void commitglines(void *arg
) {
237 glinebuf
*gbuf
= (glinebuf
*)arg
;
238 glinebufcommit(gbuf
, 1);
242 void gline_free(searchCtx
*ctx
, struct searchNode
*thenode
) {
243 struct gline_localdata
*localdata
;
245 chanindex
*cip
, *ncip
;
247 int i
, j
, hits
, safe
=0, delay
;
248 time_t ti
= time(NULL
);
251 localdata
= thenode
->localdata
;
253 if (localdata
->count
> NSMAX_GLINE_LIMIT
) {
254 /* need to warn the user that they have just tried to twat half the network ... */
255 ctx
->reply(senderNSExtern
, "Warning: your pattern matches too many users (%d) - nothing done.", localdata
->count
);
261 gbuf
= malloc(sizeof(glinebuf
));
262 glinebufinit(gbuf
, 0);
264 if (ctx
->searchcmd
== reg_chansearch
) {
265 for (i
=0;i
<CHANNELHASHSIZE
;i
++) {
266 for (cip
=chantable
[i
];cip
;cip
=ncip
) {
268 if (cip
!= NULL
&& cip
->channel
!= NULL
&& cip
->marker
== localdata
->marker
) {
269 for (j
=0;j
<cip
->channel
->users
->hashsize
;j
++) {
270 if (cip
->channel
->users
->content
[j
]==nouser
)
273 if ((np
=getnickbynumeric(cip
->channel
->users
->content
[j
]))) {
274 if(!glineuser(gbuf
, np
, localdata
, ti
))
281 } else if (ctx
->searchcmd
== reg_nicksearch
) {
282 for (i
=0;i
<NICKHASHSIZE
;i
++) {
283 for (np
=nicktable
[i
];np
;np
=nnp
) {
285 if (np
->marker
== localdata
->marker
) {
286 if(!glineuser(gbuf
, np
, localdata
, ti
))
292 for (i
= whowasoffset
; i
< whowasoffset
+ whowasmax
; i
++) {
293 ww
= &whowasrecs
[i
% whowasmax
];
295 if (ww
->type
== WHOWAS_UNUSED
)
298 if (ww
->marker
== localdata
->marker
) {
299 if(!glineuser(gbuf
, &ww
->nick
, localdata
, ti
))
305 glinebufcounthits(gbuf
, &hits
, NULL
);
307 delay
= (rand() % (localdata
->maxdelay
+ 1 - localdata
->mindelay
)) + localdata
->mindelay
;
310 scheduleoneshot(time(NULL
) + delay
, commitglines
, gbuf
);
316 ctx
->reply(senderNSExtern
, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe
);
317 /* notify opers of the action */
318 ctx
->wall(NL_GLINES
, "%s/%s glined %d %s via %s for %s [%d untouched].", senderNSExtern
->nick
, senderNSExtern
->authname
, (localdata
->count
- safe
),
319 (localdata
->count
- safe
) != 1 ? "users" : "user", (ctx
->searchcmd
== reg_chansearch
) ? "chansearch" : "nicksearch", longtoduration(localdata
->duration
, 1), safe
);