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