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