]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/xline.cpp
2fd36bff5142149bfa4ec830748ed9cddfb318a8
[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 // adds a g:line
96
97 bool XLineManager::add_gline(long duration, const char* source,const char* reason,const char* hostmask)
98 {
99         bool ret = del_gline(hostmask);
100         
101         GLine item;
102         item.duration = duration;
103         strlcpy(item.hostmask,hostmask,199);
104         strlcpy(item.reason,reason,MAXBUF);
105         strlcpy(item.source,source,255);
106         item.n_matches = 0;
107         item.set_time = ServerInstance->Time();
108         
109         if (duration)
110         {
111                 glines.push_back(item);
112                 sort(glines.begin(), glines.end(),XLineManager::GSortComparison);
113         }
114         else
115         {
116                 pglines.push_back(item);
117         }
118         
119         return !ret;
120 }
121
122 // adds an e:line (exception to bans)
123
124 bool XLineManager::add_eline(long duration, const char* source, const char* reason, const char* hostmask)
125 {
126         bool ret = del_eline(hostmask);
127         ELine item;
128         item.duration = duration;
129         strlcpy(item.hostmask,hostmask,199);
130         strlcpy(item.reason,reason,MAXBUF);
131         strlcpy(item.source,source,255);
132         item.n_matches = 0;
133         item.set_time = ServerInstance->Time();
134         if (duration)
135         {
136                 elines.push_back(item);
137                 sort(elines.begin(), elines.end(),XLineManager::ESortComparison);
138         }
139         else
140         {
141                 pelines.push_back(item);
142         }
143         return !ret;
144 }
145
146 // adds a q:line
147
148 bool XLineManager::add_qline(long duration, const char* source, const char* reason, const char* nickname)
149 {
150         bool ret = del_qline(nickname);
151         QLine item;
152         item.duration = duration;
153         strlcpy(item.nick,nickname,63);
154         strlcpy(item.reason,reason,MAXBUF);
155         strlcpy(item.source,source,255);
156         item.n_matches = 0;
157         item.is_global = false;
158         item.set_time = ServerInstance->Time();
159         if (duration)
160         {
161                 qlines.push_back(item);
162                 sort(qlines.begin(), qlines.end(),XLineManager::QSortComparison);
163         }
164         else
165         {
166                 pqlines.push_back(item);
167         }
168         return !ret;
169 }
170
171 // adds a z:line
172
173 bool XLineManager::add_zline(long duration, const char* source, const char* reason, const char* ipaddr)
174 {
175         bool ret = del_zline(ipaddr);
176         ZLine item;
177         item.duration = duration;
178         if (strchr(ipaddr,'@'))
179         {
180                 while (*ipaddr != '@')
181                         ipaddr++;
182                 ipaddr++;
183         }
184         strlcpy(item.ipaddr,ipaddr,39);
185         strlcpy(item.reason,reason,MAXBUF);
186         strlcpy(item.source,source,255);
187         item.n_matches = 0;
188         item.is_global = false;
189         item.set_time = ServerInstance->Time();
190         if (duration)
191         {
192                 zlines.push_back(item);
193                 sort(zlines.begin(), zlines.end(),XLineManager::ZSortComparison);
194         }
195         else
196         {
197                 pzlines.push_back(item);
198         }
199         return !ret;
200 }
201
202 // adds a k:line
203
204 bool XLineManager::add_kline(long duration, const char* source, const char* reason, const char* hostmask)
205 {
206         bool ret = del_kline(hostmask);
207         KLine item;
208         item.duration = duration;
209         strlcpy(item.hostmask,hostmask,200);
210         strlcpy(item.reason,reason,MAXBUF);
211         strlcpy(item.source,source,255);
212         item.n_matches = 0;
213         item.set_time = ServerInstance->Time();
214         if (duration)
215         {
216                 klines.push_back(item);
217                 sort(klines.begin(), klines.end(),XLineManager::KSortComparison);
218         }
219         else
220         {
221                 pklines.push_back(item);
222         }
223         return !ret;
224 }
225
226 // deletes a g:line, returns true if the line existed and was removed
227
228 bool XLineManager::del_gline(const char* hostmask)
229 {
230         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
231         {
232                 if (!strcasecmp(hostmask,i->hostmask))
233                 {
234                         glines.erase(i);
235                         return true;
236                 }
237         }
238         for (std::vector<GLine>::iterator i = pglines.begin(); i != pglines.end(); i++)
239         {
240                 if (!strcasecmp(hostmask,i->hostmask))
241                 {
242                         pglines.erase(i);
243                         return true;
244                 }
245         }
246         return false;
247 }
248
249 // deletes a e:line, returns true if the line existed and was removed
250
251 bool XLineManager::del_eline(const char* hostmask)
252 {
253         for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
254         {
255                 if (!strcasecmp(hostmask,i->hostmask))
256                 {
257                         elines.erase(i);
258                         return true;
259                 }
260         }
261         for (std::vector<ELine>::iterator i = pelines.begin(); i != pelines.end(); i++)
262         {
263                 if (!strcasecmp(hostmask,i->hostmask))
264                 {
265                         pelines.erase(i);
266                         return true;
267                 }
268         }
269         return false;
270 }
271
272 // deletes a q:line, returns true if the line existed and was removed
273
274 bool XLineManager::del_qline(const char* nickname)
275 {
276         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
277         {
278                 if (!strcasecmp(nickname,i->nick))
279                 {
280                         qlines.erase(i);
281                         return true;
282                 }
283         }
284         for (std::vector<QLine>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
285         {
286                 if (!strcasecmp(nickname,i->nick))
287                 {
288                         pqlines.erase(i);
289                         return true;
290                 }
291         }
292         return false;
293 }
294
295 bool XLineManager::qline_make_global(const char* nickname)
296 {
297         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
298         {
299                 if (!strcasecmp(nickname,i->nick))
300                 {
301                         i->is_global = true;
302                         return true;
303                 }
304         }
305         return false;
306 }
307
308 bool XLineManager::zline_make_global(const char* ipaddr)
309 {
310         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
311         {
312                 if (!strcasecmp(ipaddr,i->ipaddr))
313                 {
314                         i->is_global = true;
315                         return true;
316                 }
317         }
318         return false;
319 }
320
321 // deletes a z:line, returns true if the line existed and was removed
322
323 bool XLineManager::del_zline(const char* ipaddr)
324 {
325         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
326         {
327                 if (!strcasecmp(ipaddr,i->ipaddr))
328                 {
329                         zlines.erase(i);
330                         return true;
331                 }
332         }
333         for (std::vector<ZLine>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
334         {
335                 if (!strcasecmp(ipaddr,i->ipaddr))
336                 {
337                         pzlines.erase(i);
338                         return true;
339                 }
340         }
341         return false;
342 }
343
344 // deletes a k:line, returns true if the line existed and was removed
345
346 bool XLineManager::del_kline(const char* hostmask)
347 {
348         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
349         {
350                 if (!strcasecmp(hostmask,i->hostmask))
351                 {
352                         klines.erase(i);
353                         return true;
354                 }
355         }
356         for (std::vector<KLine>::iterator i = pklines.begin(); i != pklines.end(); i++)
357         {
358                 if (!strcasecmp(hostmask,i->hostmask))
359                 {
360                         pklines.erase(i);
361                         return true;
362                 }
363         }
364         return false;
365 }
366
367 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
368
369 char* XLineManager::matches_qline(const char* nick)
370 {
371         if ((qlines.empty()) && (pqlines.empty()))
372                 return NULL;
373         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
374                 if (match(nick,i->nick))
375                         return i->reason;
376         for (std::vector<QLine>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
377                 if (match(nick,i->nick))
378                         return i->reason;
379         return NULL;
380 }
381
382 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
383
384 char* XLineManager::matches_gline(const char* host)
385 {
386         if ((glines.empty()) && (pglines.empty()))
387                 return NULL;
388         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
389                 if (match(host,i->hostmask, true))
390                         return i->reason;
391         for (std::vector<GLine>::iterator i = pglines.begin(); i != pglines.end(); i++)
392                 if (match(host,i->hostmask, true))
393                         return i->reason;
394         return NULL;
395 }
396
397 char* XLineManager::matches_exception(const char* host)
398 {
399         if ((elines.empty()) && (pelines.empty()))
400                 return NULL;
401         char host2[MAXBUF];
402         snprintf(host2,MAXBUF,"*@%s",host);
403         for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
404                 if ((match(host,i->hostmask)) || (match(host2,i->hostmask, true)))
405                         return i->reason;
406         for (std::vector<ELine>::iterator i = pelines.begin(); i != pelines.end(); i++)
407                 if ((match(host,i->hostmask)) || (match(host2,i->hostmask, true)))
408                         return i->reason;
409         return NULL;
410 }
411
412
413 void XLineManager::gline_set_creation_time(const char* host, time_t create_time)
414 {
415         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
416         {
417                 if (!strcasecmp(host,i->hostmask))
418                 {
419                         i->set_time = create_time;
420                         return;
421                 }
422         }
423         for (std::vector<GLine>::iterator i = pglines.begin(); i != pglines.end(); i++)
424         {
425                 if (!strcasecmp(host,i->hostmask))
426                 {
427                         i->set_time = create_time;
428                         return;
429                 }
430         }
431         return ;        
432 }
433
434 void XLineManager::eline_set_creation_time(const char* host, time_t create_time)
435 {
436         for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
437         {
438                 if (!strcasecmp(host,i->hostmask))
439                 {
440                         i->set_time = create_time;
441                         return;
442                 }
443         }
444         for (std::vector<ELine>::iterator i = pelines.begin(); i != pelines.end(); i++) 
445         {
446                 if (!strcasecmp(host,i->hostmask))
447                 {
448                         i->set_time = create_time;
449                         return;
450                 }
451         }
452         return;
453 }
454
455 void XLineManager::qline_set_creation_time(const char* nick, time_t create_time)
456 {
457         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
458         {
459                 if (!strcasecmp(nick,i->nick))
460                 {
461                         i->set_time = create_time;
462                         return;
463                 }
464         }
465         for (std::vector<QLine>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
466         {
467                 if (!strcasecmp(nick,i->nick))
468                 {
469                         i->set_time = create_time;
470                         return;
471                 }
472         }
473         return;
474 }
475
476 void XLineManager::zline_set_creation_time(const char* ip, time_t create_time)
477 {
478         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
479         {
480                 if (!strcasecmp(ip,i->ipaddr))
481                 {
482                         i->set_time = create_time;
483                         return;
484                 }
485         }
486         for (std::vector<ZLine>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
487         {
488                 if (!strcasecmp(ip,i->ipaddr))
489                 {
490                         i->set_time = create_time;
491                         return;
492                 }
493         }
494         return;
495 }
496
497 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
498
499 char* XLineManager::matches_zline(const char* ipaddr)
500 {
501         if ((zlines.empty()) && (pzlines.empty()))
502                 return NULL;
503         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
504                 if (match(ipaddr,i->ipaddr, true))
505                         return i->reason;
506         for (std::vector<ZLine>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
507                 if (match(ipaddr,i->ipaddr, true))
508                         return i->reason;
509         return NULL;
510 }
511
512 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
513
514 char* XLineManager::matches_kline(const char* host)
515 {
516         if ((klines.empty()) && (pklines.empty()))
517                 return NULL;
518         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
519                 if (match(host,i->hostmask, true))
520                         return i->reason;
521         for (std::vector<KLine>::iterator i = pklines.begin(); i != pklines.end(); i++)
522                 if (match(host,i->hostmask, true))
523                         return i->reason;
524         return NULL;
525 }
526
527 bool XLineManager::GSortComparison ( const GLine one, const GLine two )
528 {
529         return (one.duration + one.set_time) < (two.duration + two.set_time);
530 }
531
532 bool XLineManager::ESortComparison ( const ELine one, const ELine two )
533 {
534         return (one.duration + one.set_time) < (two.duration + two.set_time);
535 }
536
537 bool XLineManager::ZSortComparison ( const ZLine one, const ZLine two )
538 {
539         return (one.duration + one.set_time) < (two.duration + two.set_time);
540 }
541
542 bool XLineManager::KSortComparison ( const KLine one, const KLine two )
543 {
544         return (one.duration + one.set_time) < (two.duration + two.set_time);
545 }
546
547 bool XLineManager::QSortComparison ( const QLine one, const QLine two )
548 {
549         return (one.duration + one.set_time) < (two.duration + two.set_time);
550 }
551
552 // removes lines that have expired
553
554 void XLineManager::expire_lines()
555 {
556         time_t current = ServerInstance->Time();
557
558         /* Because we now store all our XLines in sorted order using (i->duration + i->set_time) as a key, this
559          * means that to expire the XLines we just need to do a while, picking off the top few until there are
560          * none left at the head of the queue that are after the current time.
561          */
562
563         while ((glines.size()) && (current > (glines.begin()->duration + glines.begin()->set_time)))
564         {
565                 std::vector<GLine>::iterator i = glines.begin();
566                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed G-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
567                 glines.erase(i);
568         }
569
570         while ((elines.size()) && (current > (elines.begin()->duration + elines.begin()->set_time)))
571         {
572                 std::vector<ELine>::iterator i = elines.begin();
573                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed E-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
574                 elines.erase(i);
575         }
576
577         while ((zlines.size()) && (current > (zlines.begin()->duration + zlines.begin()->set_time)))
578         {
579                 std::vector<ZLine>::iterator i = zlines.begin();
580                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed Z-Line %s (set by %s %d seconds ago)",i->ipaddr,i->source,i->duration);
581                 zlines.erase(i);
582         }
583
584         while ((klines.size()) && (current > (klines.begin()->duration + klines.begin()->set_time)))
585         {
586                 std::vector<KLine>::iterator i = klines.begin();
587                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed K-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
588                 klines.erase(i);
589         }
590
591         while ((qlines.size()) && (current > (qlines.begin()->duration + qlines.begin()->set_time)))
592         {
593                 std::vector<QLine>::iterator i = qlines.begin();
594                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed Q-Line %s (set by %s %d seconds ago)",i->nick,i->source,i->duration);
595                 qlines.erase(i);
596         }
597         
598 }
599
600 // applies lines, removing clients and changing nicks etc as applicable
601
602 void XLineManager::apply_lines(const int What)
603 {
604         char reason[MAXBUF];
605         char host[MAXBUF];
606
607         if ((!glines.size()) && (!klines.size()) && (!zlines.size()) && (!qlines.size()) &&
608         (!pglines.size()) && (!pklines.size()) && (!pzlines.size()) && (!pqlines.size()))
609                 return;
610
611         CullList* Goners = new CullList(ServerInstance);
612         char* check = NULL;
613         for (std::vector<userrec*>::const_iterator u2 = ServerInstance->local_users.begin(); u2 != ServerInstance->local_users.end(); u2++)
614         {
615                 userrec* u = (userrec*)(*u2);
616                 u->MakeHost(host);
617                 if (elines.size() || pelines.size())
618                 {
619                         // ignore people matching exempts
620                         if (matches_exception(host))
621                                 continue;
622                 }
623                 if ((What & APPLY_GLINES) && (glines.size() || pglines.size()))
624                 {
625                         if ((check = matches_gline(host)))
626                         {
627                                 snprintf(reason,MAXBUF,"G-Lined: %s",check);
628                                 Goners->AddItem(u,reason);
629                         }
630                 }
631                 if ((What & APPLY_KLINES) && (klines.size() || pklines.size()))
632                 {
633                         if ((check = matches_kline(host)))
634                         {
635                                 snprintf(reason,MAXBUF,"K-Lined: %s",check);
636                                 Goners->AddItem(u,reason);
637                         }
638                 }
639                 if ((What & APPLY_QLINES) && (qlines.size() || pqlines.size()))
640                 {
641                         if ((check = matches_qline(u->nick)))
642                         {
643                                 snprintf(reason,MAXBUF,"Q-Lined: %s",check);
644                                 Goners->AddItem(u,reason);
645                         }
646                 }
647                 if ((What & APPLY_ZLINES) && (zlines.size() || pzlines.size()))
648                 {
649                         if ((check = matches_zline(u->GetIPString())))
650                         {
651                                 snprintf(reason,MAXBUF,"Z-Lined: %s",check);
652                                 Goners->AddItem(u,reason);
653                         }
654                 }
655         }
656
657         Goners->Apply();
658         DELETE(Goners);
659 }
660
661 void XLineManager::stats_k(userrec* user, string_list &results)
662 {
663         std::string sn = ServerInstance->Config->ServerName;
664         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
665                 results.push_back(sn+" 216 "+user->nick+" :"+i->hostmask+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
666         for (std::vector<KLine>::iterator i = pklines.begin(); i != pklines.end(); i++)
667                 results.push_back(sn+" 216 "+user->nick+" :"+i->hostmask+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
668 }
669
670 void XLineManager::stats_g(userrec* user, string_list &results)
671 {
672         std::string sn = ServerInstance->Config->ServerName;
673         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
674                 results.push_back(sn+" 223 "+user->nick+" :"+i->hostmask+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
675         for (std::vector<GLine>::iterator i = pglines.begin(); i != pglines.end(); i++)
676                 results.push_back(sn+" 223 "+user->nick+" :"+i->hostmask+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
677 }
678
679 void XLineManager::stats_q(userrec* user, string_list &results)
680 {
681         std::string sn = ServerInstance->Config->ServerName;
682         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
683                 results.push_back(sn+" 217 "+user->nick+" :"+i->nick+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
684         for (std::vector<QLine>::iterator i = pqlines.begin(); i != pqlines.end(); i++)
685                 results.push_back(sn+" 217 "+user->nick+" :"+i->nick+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
686 }
687
688 void XLineManager::stats_z(userrec* user, string_list &results)
689 {
690         std::string sn = ServerInstance->Config->ServerName;
691         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
692                 results.push_back(sn+" 223 "+user->nick+" :"+i->ipaddr+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
693         for (std::vector<ZLine>::iterator i = pzlines.begin(); i != pzlines.end(); i++)
694                 results.push_back(sn+" 223 "+user->nick+" :"+i->ipaddr+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
695 }
696
697 void XLineManager::stats_e(userrec* user, string_list &results)
698 {
699         std::string sn = ServerInstance->Config->ServerName;
700         for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
701                 results.push_back(sn+" 223 "+user->nick+" :"+i->hostmask+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
702         for (std::vector<ELine>::iterator i = pelines.begin(); i != pelines.end(); i++)
703                 results.push_back(sn+" 223 "+user->nick+" :"+i->hostmask+" "+ConvToStr(i->set_time)+" "+ConvToStr(i->duration)+" "+i->source+" :"+i->reason);
704 }
705
706 XLineManager::XLineManager(InspIRCd* Instance) : ServerInstance(Instance)
707 {
708 }