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