]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/xline.cpp
Add all this crapola
[user/henk/code/inspircd.git] / src / xline.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "users.h"
16 #include "modules.h"
17 #include "wildcard.h"
18 #include "xline.h"
19 #include "cull_list.h"
20
21 /* Version two, now with optimized expiry!
22  *
23  * Because the old way was horrendously slow, the new way of expiring xlines is very
24  * very efficient. I have improved the efficiency of the algorithm in two ways:
25  *
26  * (1) There are now two lists of items for each linetype. One list holds temporary
27  *     items, and the other list holds permanent items (ones which will expire).
28  *     Items which are on the permanent list are NEVER checked at all by the
29  *     expire_lines() function.
30  * (2) The temporary xline lists are always kept in strict numerical order, keyed by 
31  *     current time + duration. This means that the line which is due to expire the
32  *     soonest is always pointed at by vector::begin(), so a simple while loop can
33  *     very efficiently, very quickly and above all SAFELY pick off the first few
34  *     items in the vector which need zapping.
35  *
36  *     -- Brain
37  */
38
39 bool InitXLine(ServerConfig* conf, const char* tag)
40 {
41         return true;
42 }
43
44 bool DoneZLine(ServerConfig* conf, const char* tag)
45 {
46         conf->GetInstance()->XLines->apply_lines(APPLY_ZLINES|APPLY_PERM_ONLY);
47         return true;
48 }
49
50 bool DoneQLine(ServerConfig* conf, const char* tag)
51 {
52         conf->GetInstance()->XLines->apply_lines(APPLY_QLINES|APPLY_PERM_ONLY);
53         return true;
54 }
55
56 bool DoneKLine(ServerConfig* conf, const char* tag)
57 {
58         conf->GetInstance()->XLines->apply_lines(APPLY_KLINES|APPLY_PERM_ONLY);
59         return true;
60 }
61
62 bool DoneELine(ServerConfig* conf, const char* tag)
63 {
64         /* Yes, this is supposed to do nothing, we dont 'apply' these */
65         return true;
66 }
67
68 bool DoZLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
69 {
70         const char* reason = values[0].GetString();
71         const char* ipmask = values[1].GetString();
72         
73         conf->GetInstance()->XLines->add_zline(0,"<Config>",reason,ipmask);
74         return true;
75 }
76
77 bool DoQLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
78 {
79         const char* reason = values[0].GetString();
80         const char* nick = values[1].GetString();
81         
82         conf->GetInstance()->XLines->add_qline(0,"<Config>",reason,nick);
83         return true;
84 }
85
86 bool DoKLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
87 {
88         const char* reason = values[0].GetString();
89         const char* host = values[1].GetString();
90         
91         conf->GetInstance()->XLines->add_kline(0,"<Config>",reason,host);
92         return true;
93 }
94
95 bool DoELine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
96 {
97         const char* reason = values[0].GetString();
98         const char* host = values[1].GetString();
99         
100         conf->GetInstance()->XLines->add_eline(0,"<Config>",reason,host);
101         return true;
102 }
103
104 IdentHostPair XLineManager::IdentSplit(const std::string &ident_and_host)
105 {
106         IdentHostPair n = std::make_pair<std::string,std::string>("*","*");
107         std::string::size_type x = ident_and_host.find('@');
108         if (x != std::string::npos)
109         {
110                 n.second = ident_and_host.substr(x + 1,ident_and_host.length());
111                 n.first = ident_and_host.substr(0, x);
112                 if (!n.first.length())
113                         n.first = "*";
114                 if (!n.second.length())
115                         n.second = "*";
116         }
117         else
118         {
119                 n.second = ident_and_host;
120         }
121
122         return n;
123 }
124
125 // adds a g:line
126
127 bool XLineManager::add_gline(long duration, const char* source,const char* reason,const char* hostmask)
128 {
129         IdentHostPair ih = IdentSplit(hostmask);
130
131         bool ret = del_gline(hostmask);
132         
133         GLine* item = new GLine(ServerInstance->Time(), duration, source, reason, ih.first.c_str(), ih.second.c_str());
134         
135         if (duration)
136         {
137                 glines.push_back(item);
138                 sort(glines.begin(), glines.end(),XLineManager::GSortComparison);
139         }
140         else
141         {
142                 pglines.push_back(item);
143         }
144         
145         return !ret;
146 }
147
148 // adds an e:line (exception to bans)
149
150 bool XLineManager::add_eline(long duration, const char* source, const char* reason, const char* hostmask)
151 {
152         IdentHostPair ih = IdentSplit(hostmask);
153
154         bool ret = del_eline(hostmask);
155
156         ELine* item = new ELine(ServerInstance->Time(), duration, source, reason, ih.first.c_str(), ih.second.c_str());
157
158         if (duration)
159         {
160                 elines.push_back(item);
161                 sort(elines.begin(), elines.end(),XLineManager::ESortComparison);
162         }
163         else
164         {
165                 pelines.push_back(item);
166         }
167         return !ret;
168 }
169
170 // adds a q:line
171
172 bool XLineManager::add_qline(long duration, const char* source, const char* reason, const char* nickname)
173 {
174         bool ret = del_qline(nickname);
175         QLine* item = new QLine(ServerInstance->Time(), duration, source, reason, nickname);
176
177         if (duration)
178         {
179                 qlines.push_back(item);
180                 sort(qlines.begin(), qlines.end(),XLineManager::QSortComparison);
181         }
182         else
183         {
184                 pqlines.push_back(item);
185         }
186         return !ret;
187 }
188
189 // adds a z:line
190
191 bool XLineManager::add_zline(long duration, const char* source, const char* reason, const char* ipaddr)
192 {
193         bool ret = del_zline(ipaddr);
194
195         if (strchr(ipaddr,'@'))
196         {
197                 while (*ipaddr != '@')
198                         ipaddr++;
199                 ipaddr++;
200         }
201
202         ZLine* item = new ZLine(ServerInstance->Time(), duration, source, reason, ipaddr);
203
204         if (duration)
205         {
206                 zlines.push_back(item);
207                 sort(zlines.begin(), zlines.end(),XLineManager::ZSortComparison);
208         }
209         else
210         {
211                 pzlines.push_back(item);
212         }
213         return !ret;
214 }
215
216 // adds a k:line
217
218 bool XLineManager::add_kline(long duration, const char* source, const char* reason, const char* hostmask)
219 {
220         IdentHostPair ih = IdentSplit(hostmask);
221
222         bool ret = del_kline(hostmask);
223
224         KLine* item = new KLine(ServerInstance->Time(), duration, source, reason, ih.first.c_str(), ih.second.c_str());
225
226         if (duration)
227         {
228                 klines.push_back(item);
229                 sort(klines.begin(), klines.end(),XLineManager::KSortComparison);
230         }
231         else
232         {
233                 pklines.push_back(item);
234         }
235         return !ret;
236 }
237
238 // deletes a g:line, returns true if the line existed and was removed
239
240 bool XLineManager::del_gline(const char* hostmask)
241 {
242         IdentHostPair ih = IdentSplit(hostmask);
243         for (std::vector<GLine*>::iterator i = glines.begin(); i != glines.end(); i++)
244         {
245                 if (!strcasecmp(ih.first.c_str(),(*i)->identmask) && !strcasecmp(ih.second.c_str(),(*i)->hostmask))
246                 {
247                         delete *i;
248                         glines.erase(i);
249                         return true;
250                 }
251         }
252         for (std::vector<GLine*>::iterator i = pglines.begin(); i != pglines.end(); i++)
253         {
254                 if (!strcasecmp(ih.first.c_str(),(*i)->identmask) && !strcasecmp(ih.second.c_str(),(*i)->hostmask))
255                 {
256                         delete *i;
257                         pglines.erase(i);
258                         return true;
259                 }
260         }
261         return false;
262 }
263
264 // deletes a e:line, returns true if the line existed and was removed
265
266 bool XLineManager::del_eline(const char* hostmask)
267 {
268         IdentHostPair ih = IdentSplit(hostmask);
269         for (std::vector<ELine*>::iterator i = elines.begin(); i != elines.end(); i++)
270         {
271                 if (!strcasecmp(ih.first.c_str(),(*i)->identmask) && !strcasecmp(ih.second.c_str(),(*i)->hostmask))
272                 {
273                         delete *i;
274                         elines.erase(i);
275                         return true;
276                 }
277         }
278         for (std::vector<ELine*>::iterator i = pelines.begin(); i != pelines.end(); i++)
279         {
280                 if (!strcasecmp(ih.first.c_str(),(*i)->identmask) && !strcasecmp(ih.second.c_str(),(*i)->hostmask))
281                 {
282                         delete *i;
283                         pelines.erase(i);
284                         return true;
285                 }
286         }
287         return false;
288 }
289
290 // deletes a q:line, returns true if the line existed and was removed
291
292 bool XLineManager::del_qline(const char* nickname)
293 {
294         for (std::vector<QLine*>::iterator i = qlines.begin(); i != qlines.end(); i++)
295         {
296                 if (!strcasecmp(nickname,(*i)->nick))
297                 {
298                         delete *i;
299                         qlines.erase(i);
300                         return true;
301                 }
302         }
303         for (std::vector<QLine*>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
304         {
305                 if (!strcasecmp(nickname,(*i)->nick))
306                 {
307                         delete *i;
308                         pqlines.erase(i);
309                         return true;
310                 }
311         }
312         return false;
313 }
314
315 // deletes a z:line, returns true if the line existed and was removed
316
317 bool XLineManager::del_zline(const char* ipaddr)
318 {
319         for (std::vector<ZLine*>::iterator i = zlines.begin(); i != zlines.end(); i++)
320         {
321                 if (!strcasecmp(ipaddr,(*i)->ipaddr))
322                 {
323                         delete *i;
324                         zlines.erase(i);
325                         return true;
326                 }
327         }
328         for (std::vector<ZLine*>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
329         {
330                 if (!strcasecmp(ipaddr,(*i)->ipaddr))
331                 {
332                         delete *i;
333                         pzlines.erase(i);
334                         return true;
335                 }
336         }
337         return false;
338 }
339
340 // deletes a k:line, returns true if the line existed and was removed
341
342 bool XLineManager::del_kline(const char* hostmask)
343 {
344         IdentHostPair ih = IdentSplit(hostmask);
345         for (std::vector<KLine*>::iterator i = klines.begin(); i != klines.end(); i++)
346         {
347                 if (!strcasecmp(ih.first.c_str(),(*i)->identmask) && !strcasecmp(ih.second.c_str(),(*i)->hostmask))
348                 {
349                         delete *i;
350                         klines.erase(i);
351                         return true;
352                 }
353         }
354         for (std::vector<KLine*>::iterator i = pklines.begin(); i != pklines.end(); i++)
355         {
356                 if (!strcasecmp(ih.first.c_str(),(*i)->identmask) && !strcasecmp(ih.second.c_str(),(*i)->hostmask))
357                 {
358                         delete *i;
359                         pklines.erase(i);
360                         return true;
361                 }
362         }
363         return false;
364 }
365
366 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
367
368 QLine* XLineManager::matches_qline(const char* nick, bool permonly)
369 {
370         if ((qlines.empty()) && (pqlines.empty()))
371                 return NULL;
372         if (!permonly)
373         {
374                 for (std::vector<QLine*>::iterator i = qlines.begin(); i != qlines.end(); i++)
375                         if (match(nick,(*i)->nick))
376                                 return (*i);
377         }
378         for (std::vector<QLine*>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
379                 if (match(nick,(*i)->nick))
380                         return (*i);
381         return NULL;
382 }
383
384 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
385
386 GLine* XLineManager::matches_gline(userrec* user, bool permonly)
387 {
388         if ((glines.empty()) && (pglines.empty()))
389                 return NULL;
390         if (!permonly)
391         {
392                 for (std::vector<GLine*>::iterator i = glines.begin(); i != glines.end(); i++)
393                 {
394                         if ((match(user->ident,(*i)->identmask)))
395                         {
396                                 if ((match(user->host,(*i)->hostmask, true)) || (match(user->GetIPString(),(*i)->hostmask, true)))
397                                 {
398                                         return (*i);
399                                 }
400                         }
401                 }
402         }
403         for (std::vector<GLine*>::iterator i = pglines.begin(); i != pglines.end(); i++)
404         {
405                 if ((match(user->ident,(*i)->identmask)))
406                 {
407                         if ((match(user->host,(*i)->hostmask, true)) || (match(user->GetIPString(),(*i)->hostmask, true)))
408                         {
409                                 return (*i);
410                         }
411                 }
412         }
413         return NULL;
414 }
415
416 ELine* XLineManager::matches_exception(userrec* user, bool permonly)
417 {                       
418         if ((elines.empty()) && (pelines.empty()))
419                 return NULL;
420         char host2[MAXBUF];
421         snprintf(host2,MAXBUF,"*@%s",user->host);
422         if (!permonly)
423         {
424                 for (std::vector<ELine*>::iterator i = elines.begin(); i != elines.end(); i++)
425                 {
426                         if ((match(user->ident,(*i)->identmask)))
427                         {
428                                 if ((match(user->host,(*i)->hostmask, true)) || (match(user->GetIPString(),(*i)->hostmask, true)))
429                                 {
430                                         return (*i);
431                                 }
432                         }
433                 }
434         }
435         for (std::vector<ELine*>::iterator i = pelines.begin(); i != pelines.end(); i++)
436         {
437                 if ((match(user->ident,(*i)->identmask)))
438                 {
439                         if ((match(user->host,(*i)->hostmask, true)) || (match(user->GetIPString(),(*i)->hostmask, true)))
440                         {
441                                 return (*i);
442                         }
443                 }
444         }
445         return NULL;
446 }
447
448
449 void XLineManager::gline_set_creation_time(const char* host, time_t create_time)
450 {
451         for (std::vector<GLine*>::iterator i = glines.begin(); i != glines.end(); i++)
452         {
453                 if (!strcasecmp(host,(*i)->hostmask))
454                 {
455                         (*i)->set_time = create_time;
456                         (*i)->expiry = create_time + (*i)->duration;
457                         return;
458                 }
459         }
460         for (std::vector<GLine*>::iterator i = pglines.begin(); i != pglines.end(); i++)
461         {
462                 if (!strcasecmp(host,(*i)->hostmask))
463                 {
464                         (*i)->set_time = create_time;
465                         return;
466                 }
467         }
468         return ;        
469 }
470
471 void XLineManager::eline_set_creation_time(const char* host, time_t create_time)
472 {
473         for (std::vector<ELine*>::iterator i = elines.begin(); i != elines.end(); i++)
474         {
475                 if (!strcasecmp(host,(*i)->hostmask))
476                 {
477                         (*i)->set_time = create_time;
478                         (*i)->expiry = create_time + (*i)->duration;
479                         return;
480                 }
481         }
482         for (std::vector<ELine*>::iterator i = pelines.begin(); i != pelines.end(); i++)        
483         {
484                 if (!strcasecmp(host,(*i)->hostmask))
485                 {
486                         (*i)->set_time = create_time;
487                         return;
488                 }
489         }
490         return;
491 }
492
493 void XLineManager::qline_set_creation_time(const char* nick, time_t create_time)
494 {
495         for (std::vector<QLine*>::iterator i = qlines.begin(); i != qlines.end(); i++)
496         {
497                 if (!strcasecmp(nick,(*i)->nick))
498                 {
499                         (*i)->set_time = create_time;
500                         (*i)->expiry = create_time + (*i)->duration;
501                         return;
502                 }
503         }
504         for (std::vector<QLine*>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
505         {
506                 if (!strcasecmp(nick,(*i)->nick))
507                 {
508                         (*i)->set_time = create_time;
509                         return;
510                 }
511         }
512         return;
513 }
514
515 void XLineManager::zline_set_creation_time(const char* ip, time_t create_time)
516 {
517         for (std::vector<ZLine*>::iterator i = zlines.begin(); i != zlines.end(); i++)
518         {
519                 if (!strcasecmp(ip,(*i)->ipaddr))
520                 {
521                         (*i)->set_time = create_time;
522                         (*i)->expiry = create_time + (*i)->duration;
523                         return;
524                 }
525         }
526         for (std::vector<ZLine*>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
527         {
528                 if (!strcasecmp(ip,(*i)->ipaddr))
529                 {
530                         (*i)->set_time = create_time;
531                         return;
532                 }
533         }
534         return;
535 }
536
537 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
538
539 ZLine* XLineManager::matches_zline(const char* ipaddr, bool permonly)
540 {
541         if ((zlines.empty()) && (pzlines.empty()))
542                 return NULL;
543         if (!permonly)
544         {
545                 for (std::vector<ZLine*>::iterator i = zlines.begin(); i != zlines.end(); i++)
546                         if (match(ipaddr,(*i)->ipaddr, true))
547                                 return (*i);
548         }
549         for (std::vector<ZLine*>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
550                 if (match(ipaddr,(*i)->ipaddr, true))
551                         return (*i);
552         return NULL;
553 }
554
555 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
556
557 KLine* XLineManager::matches_kline(userrec* user, bool permonly)
558 {
559         if ((klines.empty()) && (pklines.empty()))
560                 return NULL;
561         if (!permonly)
562         {
563                 for (std::vector<KLine*>::iterator i = klines.begin(); i != klines.end(); i++)
564                 {
565                         if ((match(user->ident,(*i)->identmask)))
566                         {
567                                 if ((match(user->host,(*i)->hostmask, true)) || (match(user->GetIPString(),(*i)->hostmask, true)))
568                                 {
569                                         return (*i);
570                                 }
571                         }
572                 }
573         }
574         for (std::vector<KLine*>::iterator i = pklines.begin(); i != pklines.end(); i++)
575         {
576                 if ((match(user->ident,(*i)->identmask)))
577                 {
578                         if ((match(user->host,(*i)->hostmask, true)) || (match(user->GetIPString(),(*i)->hostmask, true)))
579                         {
580                                 return (*i);
581                         }
582                 }
583         }
584         return NULL;
585 }
586
587 bool XLineManager::GSortComparison ( const GLine* one, const GLine* two )
588 {
589         return (one->expiry) < (two->expiry);
590 }
591
592 bool XLineManager::ESortComparison ( const ELine* one, const ELine* two )
593 {
594         return (one->expiry) < (two->expiry);
595 }
596
597 bool XLineManager::ZSortComparison ( const ZLine* one, const ZLine* two )
598 {
599         return (one->expiry) < (two->expiry);
600 }
601
602 bool XLineManager::KSortComparison ( const KLine* one, const KLine* two )
603 {
604         return (one->expiry) < (two->expiry);
605 }
606
607 bool XLineManager::QSortComparison ( const QLine* one, const QLine* two )
608 {
609         return (one->expiry) < (two->expiry);
610 }
611
612 // removes lines that have expired
613
614 void XLineManager::expire_lines()
615 {
616         time_t current = ServerInstance->Time();
617
618         /* Because we now store all our XLines in sorted order using ((*i)->duration + (*i)->set_time) as a key, this
619          * means that to expire the XLines we just need to do a while, picking off the top few until there are
620          * none left at the head of the queue that are after the current time.
621          */
622
623         while ((glines.size()) && (current > (*glines.begin())->expiry))
624         {
625                 std::vector<GLine*>::iterator i = glines.begin();
626                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed G-Line %s@%s (set by %s %d seconds ago)",(*i)->identmask,(*i)->hostmask,(*i)->source,(*i)->duration);
627                 glines.erase(i);
628         }
629
630         while ((elines.size()) && (current > (*elines.begin())->expiry))
631         {
632                 std::vector<ELine*>::iterator i = elines.begin();
633                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed E-Line %s@%s (set by %s %d seconds ago)",(*i)->identmask,(*i)->hostmask,(*i)->source,(*i)->duration);
634                 elines.erase(i);
635         }
636
637         while ((zlines.size()) && (current > (*zlines.begin())->expiry))
638         {
639                 std::vector<ZLine*>::iterator i = zlines.begin();
640                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed Z-Line %s (set by %s %d seconds ago)",(*i)->ipaddr,(*i)->source,(*i)->duration);
641                 zlines.erase(i);
642         }
643
644         while ((klines.size()) && (current > (*klines.begin())->expiry))
645         {
646                 std::vector<KLine*>::iterator i = klines.begin();
647                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed K-Line %s@%s (set by %s %d seconds ago)",(*i)->identmask,(*i)->hostmask,(*i)->source,(*i)->duration);
648                 klines.erase(i);
649         }
650
651         while ((qlines.size()) && (current > (*qlines.begin())->expiry))
652         {
653                 std::vector<QLine*>::iterator i = qlines.begin();
654                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed Q-Line %s (set by %s %d seconds ago)",(*i)->nick,(*i)->source,(*i)->duration);
655                 qlines.erase(i);
656         }
657         
658 }
659
660 // applies lines, removing clients and changing nicks etc as applicable
661
662 void XLineManager::apply_lines(const int What)
663 {
664         if (!What)
665                 return;
666
667         if (What & APPLY_PERM_ONLY)
668         {
669                 char reason[MAXBUF];
670
671                 if ((!pglines.size()) && (!pklines.size()) && (!pzlines.size()) && (!pqlines.size()))
672                         return;
673
674                 CullList* Goners = new CullList(ServerInstance);
675                 XLine* check = NULL;
676                 for (std::vector<userrec*>::const_iterator u2 = ServerInstance->local_users.begin(); u2 != ServerInstance->local_users.end(); u2++)
677                 {
678                         userrec* u = (userrec*)(*u2);
679
680                         if (elines.size() || pelines.size())
681                                 if (matches_exception(u))
682                                         continue;
683
684                         if ((What & APPLY_GLINES) && pglines.size())
685                         {
686                                 if ((check = matches_gline(u,true)))
687                                 {
688                                         snprintf(reason,MAXBUF,"G-Lined: %s",check->reason);
689                                         Goners->AddItem(u,reason);
690                                 }
691                         }
692
693                         if ((What & APPLY_KLINES) && pklines.size())
694                         {
695                                 if ((check = matches_kline(u,true)))
696                                 {
697                                         snprintf(reason,MAXBUF,"K-Lined: %s",check->reason);
698                                         Goners->AddItem(u,reason);
699                                 }
700                         }
701
702                         if ((What & APPLY_QLINES) && pqlines.size())
703                         {
704                                 if ((check = matches_qline(u->nick,true)))
705                                 {
706                                         snprintf(reason,MAXBUF,"Q-Lined: %s",check->reason);
707                                         Goners->AddItem(u,reason);
708                                 }
709                         }
710
711                         if ((What & APPLY_ZLINES) && pzlines.size())
712                         {
713                                 if ((check = matches_zline(u->GetIPString(),true)))
714                                 {
715                                         snprintf(reason,MAXBUF,"Z-Lined: %s",check->reason);
716                                         Goners->AddItem(u,reason);
717                                 }
718                         }
719                 }
720
721                 Goners->Apply();
722                 DELETE(Goners);
723         }
724         else
725         {
726                 char reason[MAXBUF];
727
728                 if ((!glines.size()) && (!klines.size()) && (!zlines.size()) && (!qlines.size()) &&
729                 (!pglines.size()) && (!pklines.size()) && (!pzlines.size()) && (!pqlines.size()))
730                         return;
731         
732                 CullList* Goners = new CullList(ServerInstance);
733                 XLine* check = NULL;
734                 for (std::vector<userrec*>::const_iterator u2 = ServerInstance->local_users.begin(); u2 != ServerInstance->local_users.end(); u2++)
735                 {
736                         userrec* u = (userrec*)(*u2);
737
738                         if (elines.size() || pelines.size())
739                         {
740                                 // ignore people matching exempts
741                                 if (matches_exception(u))
742                                         continue;
743                         }
744                         if ((What & APPLY_GLINES) && (glines.size() || pglines.size()))
745                         {
746                                 if ((check = matches_gline(u)))
747                                 {
748                                         snprintf(reason,MAXBUF,"G-Lined: %s",check->reason);
749                                         Goners->AddItem(u,reason);
750                                 }
751                         }
752                         if ((What & APPLY_KLINES) && (klines.size() || pklines.size()))
753                         {
754                                 if ((check = matches_kline(u)))
755                                 {
756                                         snprintf(reason,MAXBUF,"K-Lined: %s",check->reason);
757                                         Goners->AddItem(u,reason);
758                                 }
759                         }
760                         if ((What & APPLY_QLINES) && (qlines.size() || pqlines.size()))
761                         {
762                                 if ((check = matches_qline(u->nick)))
763                                 {
764                                         snprintf(reason,MAXBUF,"Q-Lined: %s",check->reason);
765                                         Goners->AddItem(u,reason);
766                                 }
767                         }
768                         if ((What & APPLY_ZLINES) && (zlines.size() || pzlines.size()))
769                         {
770                                 if ((check = matches_zline(u->GetIPString())))
771                                 {
772                                         snprintf(reason,MAXBUF,"Z-Lined: %s",check->reason);
773                                         Goners->AddItem(u,reason);
774                                 }
775                         }
776                 }
777
778                 Goners->Apply();
779                 DELETE(Goners);
780         }
781 }
782
783 void XLineManager::stats_k(userrec* user, string_list &results)
784 {
785         std::string sn = ServerInstance->Config->ServerName;
786         for (std::vector<KLine*>::iterator i = klines.begin(); i != klines.end(); i++)
787                 results.push_back(sn+" 216 "+user->nick+" :"+(*i)->identmask+"@"+(*i)->hostmask+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
788         for (std::vector<KLine*>::iterator i = pklines.begin(); i != pklines.end(); i++)
789                 results.push_back(sn+" 216 "+user->nick+" :"+(*i)->identmask+"@"+(*i)->hostmask+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
790 }
791
792 void XLineManager::stats_g(userrec* user, string_list &results)
793 {
794         std::string sn = ServerInstance->Config->ServerName;
795         for (std::vector<GLine*>::iterator i = glines.begin(); i != glines.end(); i++)
796                 results.push_back(sn+" 223 "+user->nick+" :"+(*i)->identmask+"@"+(*i)->hostmask+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
797         for (std::vector<GLine*>::iterator i = pglines.begin(); i != pglines.end(); i++)
798                 results.push_back(sn+" 223 "+user->nick+" :"+(*i)->identmask+"@"+(*i)->hostmask+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
799 }
800
801 void XLineManager::stats_q(userrec* user, string_list &results)
802 {
803         std::string sn = ServerInstance->Config->ServerName;
804         for (std::vector<QLine*>::iterator i = qlines.begin(); i != qlines.end(); i++)
805                 results.push_back(sn+" 217 "+user->nick+" :"+(*i)->nick+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
806         for (std::vector<QLine*>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
807                 results.push_back(sn+" 217 "+user->nick+" :"+(*i)->nick+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
808 }
809
810 void XLineManager::stats_z(userrec* user, string_list &results)
811 {
812         std::string sn = ServerInstance->Config->ServerName;
813         for (std::vector<ZLine*>::iterator i = zlines.begin(); i != zlines.end(); i++)
814                 results.push_back(sn+" 223 "+user->nick+" :"+(*i)->ipaddr+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
815         for (std::vector<ZLine*>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
816                 results.push_back(sn+" 223 "+user->nick+" :"+(*i)->ipaddr+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
817 }
818
819 void XLineManager::stats_e(userrec* user, string_list &results)
820 {
821         std::string sn = ServerInstance->Config->ServerName;
822         for (std::vector<ELine*>::iterator i = elines.begin(); i != elines.end(); i++)
823                 results.push_back(sn+" 223 "+user->nick+" :"+(*i)->identmask+"@"+(*i)->hostmask+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
824         for (std::vector<ELine*>::iterator i = pelines.begin(); i != pelines.end(); i++)
825                 results.push_back(sn+" 223 "+user->nick+" :"+(*i)->identmask+"@"+(*i)->hostmask+" "+ConvToStr((*i)->set_time)+" "+ConvToStr((*i)->duration)+" "+(*i)->source+" :"+(*i)->reason);
826 }
827
828 XLineManager::XLineManager(InspIRCd* Instance) : ServerInstance(Instance)
829 {
830 }