]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules.cpp
Started removal of server linking code from core and implementation of socket API
[user/henk/code/inspircd.git] / src / modules.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 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_config.h"
20 #include "inspircd.h"
21 #include "inspircd_io.h"
22 #include "inspircd_util.h"
23 #include <unistd.h>
24 #include <sys/errno.h>
25
26 #ifdef USE_KQUEUE
27 #include <sys/types.h>
28 #include <sys/event.h>
29 #include <sys/time.h>
30 #endif
31
32 #ifdef USE_EPOLL
33 #include <sys/epoll.h>
34 #endif
35
36 #include <time.h>
37 #include <string>
38 #ifdef GCC3
39 #include <ext/hash_map>
40 #else
41 #include <hash_map>
42 #endif
43 #include <map>
44 #include <sstream>
45 #include <vector>
46 #include <deque>
47 #include "connection.h"
48 #include "users.h"
49 #include "servers.h"
50 #include "ctables.h"
51 #include "globals.h"
52 #include "modules.h"
53 #include "dynamic.h"
54 #include "wildcard.h"
55 #include "message.h"
56 #include "mode.h"
57 #include "xline.h"
58 #include "commands.h"
59 #include "inspstring.h"
60 #include "helperfuncs.h"
61 #include "hashcomp.h"
62 #include "socket.h"
63
64 #ifdef USE_KQUEUE
65 extern int kq;
66 #endif
67
68 #ifdef USE_EPOLL
69 int ep;
70 #endif
71
72 extern int MODCOUNT;
73 extern std::vector<Module*> modules;
74 extern std::vector<ircd_module*> factory;
75
76 extern std::vector<std::string> include_stack;
77
78 extern std::vector<InspSocket*> module_sockets;
79
80 extern time_t TIME;
81
82 extern int LogLevel;
83 extern char ServerName[MAXBUF];
84 extern char Network[MAXBUF];
85 extern char ServerDesc[MAXBUF];
86 extern char AdminName[MAXBUF];
87 extern char AdminEmail[MAXBUF];
88 extern char AdminNick[MAXBUF];
89 extern char diepass[MAXBUF];
90 extern char restartpass[MAXBUF];
91 extern char motd[MAXBUF];
92 extern char rules[MAXBUF];
93 extern char list[MAXBUF];
94 extern char PrefixQuit[MAXBUF];
95 extern char DieValue[MAXBUF];
96
97 extern int debugging;
98 extern int WHOWAS_STALE;
99 extern int WHOWAS_MAX;
100 extern int DieDelay;
101 extern time_t startup_time;
102 extern int NetBufferSize;
103 extern int MaxWhoResults;
104 extern time_t nb_start;
105
106 extern std::vector<std::string> module_names;
107
108 extern int boundPortCount;
109 extern int portCount;
110 extern int SERVERportCount;
111 extern int ports[MAXSOCKS];
112 extern int defaultRoute;
113
114 extern std::vector<long> auth_cookies;
115 extern std::stringstream config_f;
116
117 extern serverrec* me[32];
118
119 extern FILE *log_file;
120
121 extern userrec* fd_ref_table[65536];
122
123 typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, irc::StrHashComp> user_hash;
124 typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, irc::StrHashComp> chan_hash;
125 typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, irc::InAddr_HashComp> address_cache;
126 typedef nspace::hash_map<std::string, WhoWasUser*, nspace::hash<string>, irc::StrHashComp> whowas_hash;
127 typedef std::deque<command_t> command_table;
128
129
130 extern user_hash clientlist;
131 extern chan_hash chanlist;
132 extern whowas_hash whowas;
133 extern command_table cmdlist;
134 extern file_cache MOTD;
135 extern file_cache RULES;
136 extern address_cache IP;
137
138
139 // class type for holding an extended mode character - internal to core
140
141 class ExtMode : public classbase
142 {
143 public:
144         char modechar;
145         int type;
146         bool needsoper;
147         int params_when_on;
148         int params_when_off;
149         bool list;
150         ExtMode(char mc, int ty, bool oper, int p_on, int p_off) : modechar(mc), type(ty), needsoper(oper), params_when_on(p_on), params_when_off(p_off) { };
151 };                                     
152
153 typedef std::vector<ExtMode> ExtModeList;
154 typedef ExtModeList::iterator ExtModeListIter;
155
156
157 ExtModeList EMode;
158
159 // returns true if an extended mode character is in use
160 bool ModeDefined(char modechar, int type)
161 {
162         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
163         {
164                 if ((i->modechar == modechar) && (i->type == type))
165                 {
166                         return true;
167                 }
168         }
169         return false;
170 }
171
172 bool ModeIsListMode(char modechar, int type)
173 {
174         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
175         {
176                 if ((i->modechar == modechar) && (i->type == type) && (i->list == true))
177                 {
178                         return true;
179                 }
180         }
181         return false;
182 }
183
184 bool ModeDefinedOper(char modechar, int type)
185 {
186         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
187         {
188                 if ((i->modechar == modechar) && (i->type == type) && (i->needsoper == true))
189                 {
190                         return true;
191                 }
192         }
193         return false;
194 }
195
196 // returns number of parameters for a custom mode when it is switched on
197 int ModeDefinedOn(char modechar, int type)
198 {
199         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
200         {
201                 if ((i->modechar == modechar) && (i->type == type))
202                 {
203                         return i->params_when_on;
204                 }
205         }
206         return 0;
207 }
208
209 // returns number of parameters for a custom mode when it is switched on
210 int ModeDefinedOff(char modechar, int type)
211 {
212         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
213         {
214                 if ((i->modechar == modechar) && (i->type == type))
215                 {
216                         return i->params_when_off;
217                 }
218         }
219         return 0;
220 }
221
222 // returns true if an extended mode character is in use
223 bool DoAddExtendedMode(char modechar, int type, bool requires_oper, int params_on, int params_off)
224 {
225         if (ModeDefined(modechar,type)) {
226                 return false;
227         }
228         EMode.push_back(ExtMode(modechar,type,requires_oper,params_on,params_off));
229         return true;
230 }
231
232 // turns a mode into a listmode
233 void ModeMakeList(char modechar)
234 {
235         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
236         {
237                 if ((i->modechar == modechar) && (i->type == MT_CHANNEL))
238                 {
239                         i->list = true;
240                         return;
241                 }
242         }
243         return;
244 }
245
246 // version is a simple class for holding a modules version number
247
248 Version::Version(int major, int minor, int revision, int build, int flags) : Major(major), Minor(minor), Revision(revision), Build(build), Flags(flags) { };
249
250 // admin is a simple class for holding a server's administrative info
251
252 Admin::Admin(std::string name, std::string email, std::string nick) : Name(name), Email(email), Nick(nick) { };
253
254 Request::Request(char* anydata, Module* src, Module* dst) : data(anydata), source(src), dest(dst) { };
255
256 char* Request::GetData()
257 {
258         return this->data;
259 }
260
261 Module* Request::GetSource()
262 {
263         return this->source;
264 }
265
266 Module* Request::GetDest()
267 {
268         return this->dest;
269 }
270
271 char* Request::Send()
272 {
273         if (this->dest)
274         {
275                 return dest->OnRequest(this);
276         }
277         else
278         {
279                 return NULL;
280         }
281 }
282
283 Event::Event(char* anydata, Module* src, std::string eventid) : data(anydata), source(src), id(eventid) { };
284
285 char* Event::GetData()
286 {
287         return this->data;
288 }
289
290 Module* Event::GetSource()
291 {
292         return this->source;
293 }
294
295 char* Event::Send()
296 {
297         FOREACH_MOD OnEvent(this);
298         return NULL;
299 }
300
301 std::string Event::GetEventID()
302 {
303         return this->id;
304 }
305
306
307 // These declarations define the behavours of the base class Module (which does nothing at all)
308                 Module::Module() { }
309                 Module::~Module() { }
310 void            Module::OnUserConnect(userrec* user) { }
311 void            Module::OnUserQuit(userrec* user) { }
312 void            Module::OnUserDisconnect(userrec* user) { }
313 void            Module::OnUserJoin(userrec* user, chanrec* channel) { }
314 void            Module::OnUserPart(userrec* user, chanrec* channel) { }
315 void            Module::OnPacketTransmit(std::string &data, std::string serv) { }
316 void            Module::OnPacketReceive(std::string &data, std::string serv) { }
317 void            Module::OnRehash() { }
318 void            Module::OnServerRaw(std::string &raw, bool inbound, userrec* user) { }
319 int             Module::OnUserPreJoin(userrec* user, chanrec* chan, const char* cname) { return 0; }
320 int             Module::OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list &params) { return false; }
321 Version         Module::GetVersion() { return Version(1,0,0,0,VF_VENDOR); }
322 void            Module::OnOper(userrec* user) { };
323 void            Module::OnInfo(userrec* user) { };
324 void            Module::OnWhois(userrec* source, userrec* dest) { };
325 int             Module::OnUserPreInvite(userrec* source,userrec* dest,chanrec* channel) { return 0; };
326 int             Module::OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text) { return 0; };
327 int             Module::OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text) { return 0; };
328 int             Module::OnUserPreNick(userrec* user, std::string newnick) { return 0; };
329 void            Module::OnUserPostNick(userrec* user, std::string oldnick) { };
330 int             Module::OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type) { return ACR_DEFAULT; };
331 string_list     Module::OnUserSync(userrec* user) { string_list empty; return empty; }
332 string_list     Module::OnChannelSync(chanrec* chan) { string_list empty; return empty; }
333 void            Module::On005Numeric(std::string &output) { };
334 int             Module::OnKill(userrec* source, userrec* dest, std::string reason) { return 0; };
335 void            Module::OnLoadModule(Module* mod,std::string name) { };
336 void            Module::OnUnloadModule(Module* mod,std::string name) { };
337 void            Module::OnBackgroundTimer(time_t curtime) { };
338 void            Module::OnSendList(userrec* user, chanrec* channel, char mode) { };
339 int             Module::OnPreCommand(std::string command, char **parameters, int pcnt, userrec *user) { return 0; };
340 bool            Module::OnCheckReady(userrec* user) { return true; };
341 void            Module::OnUserRegister(userrec* user) { };
342 int             Module::OnUserPreKick(userrec* source, userrec* user, chanrec* chan, std::string reason) { return 0; };
343 void            Module::OnUserKick(userrec* source, userrec* user, chanrec* chan, std::string reason) { };
344 int             Module::OnRawMode(userrec* user, chanrec* chan, char mode, std::string param, bool adding, int pcnt) { return 0; };
345 int             Module::OnCheckInvite(userrec* user, chanrec* chan) { return 0; };
346 int             Module::OnCheckKey(userrec* user, chanrec* chan, std::string keygiven) { return 0; };
347 int             Module::OnCheckLimit(userrec* user, chanrec* chan) { return 0; };
348 int             Module::OnCheckBan(userrec* user, chanrec* chan) { return 0; };
349 void            Module::OnStats(char symbol) { };
350 int             Module::OnChangeLocalUserHost(userrec* user, std::string newhost) { return 0; };
351 int             Module::OnChangeLocalUserGECOS(userrec* user, std::string newhost) { return 0; };
352 int             Module::OnLocalTopicChange(userrec* user, chanrec* chan, std::string topic) { return 0; };
353 int             Module::OnMeshToken(char token,string_list params,serverrec* source,serverrec* reply, std::string tcp_host,std::string ipaddr,int port) { return 0; };
354 void            Module::OnEvent(Event* event) { return; };
355 char*           Module::OnRequest(Request* request) { return NULL; };
356 int             Module::OnOperCompare(std::string password, std::string input) { return 0; };
357 void            Module::OnGlobalOper(userrec* user) { };
358 void            Module::OnGlobalConnect(userrec* user) { };
359 int             Module::OnAddBan(userrec* source, chanrec* channel,std::string banmask) { return 0; };
360 int             Module::OnDelBan(userrec* source, chanrec* channel,std::string banmask) { return 0; };
361 void            Module::OnRawSocketAccept(int fd, std::string ip, int localport) { };
362 int             Module::OnRawSocketWrite(int fd, char* buffer, int count) { return 0; };
363 void            Module::OnRawSocketClose(int fd) { };
364 int             Module::OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) { return 0; };
365
366 // server is a wrapper class that provides methods to all of the C-style
367 // exports in the core
368 //
369
370 Server::Server()
371 {
372 }
373
374 Server::~Server()
375 {
376 }
377
378 void Server::SendOpers(std::string s)
379 {
380         WriteOpers("%s",s.c_str());
381 }
382
383 bool Server::MatchText(std::string sliteral, std::string spattern)
384 {
385         char literal[MAXBUF],pattern[MAXBUF];
386         strlcpy(literal,sliteral.c_str(),MAXBUF);
387         strlcpy(pattern,spattern.c_str(),MAXBUF);
388         return match(literal,pattern);
389 }
390
391 void Server::SendToModeMask(std::string modes, int flags, std::string text)
392 {
393         WriteMode(modes.c_str(),flags,"%s",text.c_str());
394 }
395
396 chanrec* Server::JoinUserToChannel(userrec* user, std::string cname, std::string key)
397 {
398         return add_channel(user,cname.c_str(),key.c_str(),false);
399 }
400
401 chanrec* Server::PartUserFromChannel(userrec* user, std::string cname, std::string reason)
402 {
403         return del_channel(user,cname.c_str(),reason.c_str(),false);
404 }
405
406 chanuserlist Server::GetUsers(chanrec* chan)
407 {
408         chanuserlist userl;
409         userl.clear();
410         std::vector<char*> *list = chan->GetUsers();
411         for (std::vector<char*>::iterator i = list->begin(); i != list->end(); i++)
412         {
413                 char* o = *i;
414                 userl.push_back((userrec*)o);
415         }
416         return userl;
417 }
418 void Server::ChangeUserNick(userrec* user, std::string nickname)
419 {
420         force_nickchange(user,nickname.c_str());
421 }
422
423 void Server::QuitUser(userrec* user, std::string reason)
424 {
425         kill_link(user,reason.c_str());
426 }
427
428 bool Server::IsUlined(std::string server)
429 {
430         return is_uline(server.c_str());
431 }
432
433 void Server::CallCommandHandler(std::string commandname, char** parameters, int pcnt, userrec* user)
434 {
435         call_handler(commandname.c_str(),parameters,pcnt,user);
436 }
437
438 void Server::Log(int level, std::string s)
439 {
440         log(level,"%s",s.c_str());
441 }
442
443 void Server::AddCommand(char* cmd, handlerfunc f, char flags, int minparams, char* source)
444 {
445         createcommand(cmd,f,flags,minparams,source);
446 }
447
448 void Server::SendMode(char **parameters, int pcnt, userrec *user)
449 {
450         server_mode(parameters,pcnt,user);
451 }
452
453 void Server::Send(int Socket, std::string s)
454 {
455         Write(Socket,"%s",s.c_str());
456 }
457
458 void Server::SendServ(int Socket, std::string s)
459 {
460         WriteServ(Socket,"%s",s.c_str());
461 }
462
463 void Server::SendFrom(int Socket, userrec* User, std::string s)
464 {
465         WriteFrom(Socket,User,"%s",s.c_str());
466 }
467
468 void Server::SendTo(userrec* Source, userrec* Dest, std::string s)
469 {
470         if (!Source)
471         {
472                 // if source is NULL, then the message originates from the local server
473                 Write(Dest->fd,":%s %s",this->GetServerName().c_str(),s.c_str());
474         }
475         else
476         {
477                 // otherwise it comes from the user specified
478                 WriteTo(Source,Dest,"%s",s.c_str());
479         }
480 }
481
482 void Server::SendChannelServerNotice(std::string ServName, chanrec* Channel, std::string text)
483 {
484         WriteChannelWithServ((char*)ServName.c_str(), Channel, "%s", text.c_str());
485 }
486
487 void Server::SendChannel(userrec* User, chanrec* Channel, std::string s,bool IncludeSender)
488 {
489         if (IncludeSender)
490         {
491                 WriteChannel(Channel,User,"%s",s.c_str());
492         }
493         else
494         {
495                 ChanExceptSender(Channel,User,"%s",s.c_str());
496         }
497 }
498
499 bool Server::CommonChannels(userrec* u1, userrec* u2)
500 {
501         return (common_channels(u1,u2) != 0);
502 }
503
504 void Server::SendCommon(userrec* User, std::string text,bool IncludeSender)
505 {
506         if (IncludeSender)
507         {
508                 WriteCommon(User,"%s",text.c_str());
509         }
510         else
511         {
512                 WriteCommonExcept(User,"%s",text.c_str());
513         }
514 }
515
516 void Server::SendWallops(userrec* User, std::string text)
517 {
518         WriteWallOps(User,false,"%s",text.c_str());
519 }
520
521 void Server::ChangeHost(userrec* user, std::string host)
522 {
523         ChangeDisplayedHost(user,host.c_str());
524 }
525
526 void Server::ChangeGECOS(userrec* user, std::string gecos)
527 {
528         ChangeName(user,gecos.c_str());
529 }
530
531 bool Server::IsNick(std::string nick)
532 {
533         return (isnick(nick.c_str()) != 0);
534 }
535
536 userrec* Server::FindNick(std::string nick)
537 {
538         return Find(nick);
539 }
540
541 userrec* Server::FindDescriptor(int socket)
542 {
543         return (socket < 65536 ? fd_ref_table[socket] : NULL);
544 }
545
546 chanrec* Server::FindChannel(std::string channel)
547 {
548         return FindChan(channel.c_str());
549 }
550
551 std::string Server::ChanMode(userrec* User, chanrec* Chan)
552 {
553         return cmode(User,Chan);
554 }
555
556 bool Server::IsOnChannel(userrec* User, chanrec* Chan)
557 {
558         return has_channel(User,Chan);
559 }
560
561 std::string Server::GetServerName()
562 {
563         return getservername();
564 }
565
566 std::string Server::GetNetworkName()
567 {
568         return getnetworkname();
569 }
570
571 std::string Server::GetServerDescription()
572 {
573         return getserverdesc();
574 }
575
576 Admin Server::GetAdmin()
577 {
578         return Admin(getadminname(),getadminemail(),getadminnick());
579 }
580
581
582
583 bool Server::AddExtendedMode(char modechar, int type, bool requires_oper, int params_when_on, int params_when_off)
584 {
585         if (((modechar >= 'A') && (modechar <= 'Z')) || ((modechar >= 'a') && (modechar <= 'z')))
586         {
587                 if (type == MT_SERVER)
588                 {
589                         log(DEBUG,"*** API ERROR *** Modes of type MT_SERVER are reserved for future expansion");
590                         return false;
591                 }
592                 if (((params_when_on>0) || (params_when_off>0)) && (type == MT_CLIENT))
593                 {
594                         log(DEBUG,"*** API ERROR *** Parameters on MT_CLIENT modes are not supported");
595                         return false;
596                 }
597                 if ((params_when_on>1) || (params_when_off>1))
598                 {
599                         log(DEBUG,"*** API ERROR *** More than one parameter for an MT_CHANNEL mode is not yet supported");
600                         return false;
601                 }
602                 return DoAddExtendedMode(modechar,type,requires_oper,params_when_on,params_when_off);
603         }
604         else
605         {
606                 log(DEBUG,"*** API ERROR *** Muppet modechar detected.");
607         }
608         return false;
609 }
610
611 bool Server::AddExtendedListMode(char modechar)
612 {
613         bool res = DoAddExtendedMode(modechar,MT_CHANNEL,false,1,1);
614         if (res)
615                 ModeMakeList(modechar);
616         return res;
617 }
618
619 int Server::CountUsers(chanrec* c)
620 {
621         return usercount(c);
622 }
623
624
625 bool Server::UserToPseudo(userrec* user,std::string message)
626 {
627         unsigned int old_fd = user->fd;
628         user->fd = FD_MAGIC_NUMBER;
629         user->ClearBuffer();
630         Write(old_fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,message.c_str());
631 #ifdef USE_KQUEUE
632         struct kevent ke;
633         EV_SET(&ke, old_fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
634         int i = kevent(kq, &ke, 1, 0, 0, NULL);
635         if (i == -1)
636         {
637                 log(DEBUG,"kqueue: Failed to remove user from queue!");
638         }
639 #endif
640 #ifdef USE_EPOLL
641         struct epoll_event ev;
642         ev.events = EPOLLIN | EPOLLET;
643         ev.data.fd = old_fd;
644         int i = epoll_ctl(ep, EPOLL_CTL_DEL, old_fd, &ev);
645         if (i < 0)
646         {
647                 log(DEBUG,"epoll: List deletion failure!");
648         }
649 #endif
650
651         shutdown(old_fd,2);
652         close(old_fd);
653         return true;
654 }
655
656 bool Server::PseudoToUser(userrec* alive,userrec* zombie,std::string message)
657 {
658         zombie->fd = alive->fd;
659         alive->fd = FD_MAGIC_NUMBER;
660         alive->ClearBuffer();
661         Write(zombie->fd,":%s!%s@%s NICK %s",alive->nick,alive->ident,alive->host,zombie->nick);
662         kill_link(alive,message.c_str());
663         fd_ref_table[zombie->fd] = zombie;
664         for (int i = 0; i != MAXCHANS; i++)
665         {
666                 if (zombie->chans[i].channel != NULL)
667                 {
668                         if (zombie->chans[i].channel->name)
669                         {
670                                 chanrec* Ptr = zombie->chans[i].channel;
671                                 WriteFrom(zombie->fd,zombie,"JOIN %s",Ptr->name);
672                                 if (Ptr->topicset)
673                                 {
674                                         WriteServ(zombie->fd,"332 %s %s :%s", zombie->nick, Ptr->name, Ptr->topic);
675                                         WriteServ(zombie->fd,"333 %s %s %s %d", zombie->nick, Ptr->name, Ptr->setby, Ptr->topicset);
676                                 }
677                                 userlist(zombie,Ptr);
678                                 WriteServ(zombie->fd,"366 %s %s :End of /NAMES list.", zombie->nick, Ptr->name);
679
680                         }
681                 }
682         }
683         return true;
684 }
685
686 void Server::AddGLine(long duration, std::string source, std::string reason, std::string hostmask)
687 {
688         add_gline(duration, source.c_str(), reason.c_str(), hostmask.c_str());
689 }
690
691 void Server::AddQLine(long duration, std::string source, std::string reason, std::string nickname)
692 {
693         add_qline(duration, source.c_str(), reason.c_str(), nickname.c_str());
694 }
695
696 void Server::AddZLine(long duration, std::string source, std::string reason, std::string ipaddr)
697 {
698         add_zline(duration, source.c_str(), reason.c_str(), ipaddr.c_str());
699 }
700
701 void Server::AddKLine(long duration, std::string source, std::string reason, std::string hostmask)
702 {
703         add_kline(duration, source.c_str(), reason.c_str(), hostmask.c_str());
704 }
705
706 void Server::AddELine(long duration, std::string source, std::string reason, std::string hostmask)
707 {
708         add_eline(duration, source.c_str(), reason.c_str(), hostmask.c_str());
709 }
710
711 bool Server::DelGLine(std::string hostmask)
712 {
713         return del_gline(hostmask.c_str());
714 }
715
716 bool Server::DelQLine(std::string nickname)
717 {
718         return del_qline(nickname.c_str());
719 }
720
721 bool Server::DelZLine(std::string ipaddr)
722 {
723         return del_zline(ipaddr.c_str());
724 }
725
726 bool Server::DelKLine(std::string hostmask)
727 {
728         return del_kline(hostmask.c_str());
729 }
730
731 bool Server::DelELine(std::string hostmask)
732 {
733         return del_eline(hostmask.c_str());
734 }
735
736 long Server::CalcDuration(std::string delta)
737 {
738         return duration(delta.c_str());
739 }
740
741 bool Server::IsValidMask(std::string mask)
742 {
743         const char* dest = mask.c_str();
744         if (strchr(dest,'!')==0)
745                 return false;
746         if (strchr(dest,'@')==0)
747                 return false;
748         for (unsigned int i = 0; i < strlen(dest); i++)
749                 if (dest[i] < 32)
750                         return false;
751         for (unsigned int i = 0; i < strlen(dest); i++)
752                 if (dest[i] > 126)
753                         return false;
754         unsigned int c = 0;
755         for (unsigned int i = 0; i < strlen(dest); i++)
756                 if (dest[i] == '!')
757                         c++;
758         if (c>1)
759                 return false;
760         c = 0;
761         for (unsigned int i = 0; i < strlen(dest); i++)
762                 if (dest[i] == '@')
763                         c++;
764         if (c>1)
765                 return false;
766
767         return true;
768 }
769
770 void Server::MeshSendAll(std::string text)
771 {
772         NetSendToAll((char*)text.c_str());
773 }
774
775 void Server::MeshSendCommon(userrec* user, std::string text)
776 {
777         if (user)
778                 NetSendToCommon(user,(char*)text.c_str());
779 }
780
781 void Server::MeshSendAllAlive(std::string text)
782 {
783         NetSendToAllAlive((char*)text.c_str());
784 }
785
786 void Server::MeshSendUnicast(std::string destination, std::string text)
787 {
788         NetSendToOne((char*)destination.c_str(),(char*)text.c_str());
789 }
790
791 void Server::MeshSendAllExcept(std::string target, std::string text)
792 {
793         NetSendToAllExcept(target.c_str(),(char*)text.c_str());
794 }
795
796 bool Server::MeshCheckChan(chanrec *c,std::string servername)
797 {
798         if (c)
799         {
800                 return ChanAnyOnThisServer(c,(char*)servername.c_str());
801         }
802         else return false;
803 }
804
805 bool Server::MeshCheckCommon(userrec* u,std::string servername)
806 {
807         if (u)
808         {
809                 return CommonOnThisServer(u,(char*)servername.c_str());
810         }
811         else return false;
812 }
813
814 Module* Server::FindModule(std::string name)
815 {
816         for (int i = 0; i <= MODCOUNT; i++)
817         {
818                 if (module_names[i] == name)
819                 {
820                         return modules[i];
821                 }
822         }
823         return NULL;
824 }
825
826 ConfigReader::ConfigReader()
827 {
828         include_stack.clear();
829         this->cache = new std::stringstream(std::stringstream::in | std::stringstream::out);
830         this->errorlog = new std::stringstream(std::stringstream::in | std::stringstream::out);
831         this->readerror = LoadConf(CONFIG_FILE,this->cache,this->errorlog);
832         if (!this->readerror)
833                 this->error = CONF_FILE_NOT_FOUND;
834 }
835
836
837 ConfigReader::~ConfigReader()
838 {
839         if (this->cache)
840                 delete this->cache;
841         if (this->errorlog)
842                 delete this->errorlog;
843 }
844
845
846 ConfigReader::ConfigReader(std::string filename)
847 {
848         this->cache = new std::stringstream(std::stringstream::in | std::stringstream::out);
849         this->errorlog = new std::stringstream(std::stringstream::in | std::stringstream::out);
850         this->readerror = LoadConf(filename.c_str(),this->cache,this->errorlog);
851         if (!this->readerror)
852                 this->error = CONF_FILE_NOT_FOUND;
853 };
854
855 std::string ConfigReader::ReadValue(std::string tag, std::string name, int index)
856 {
857         char val[MAXBUF];
858         char t[MAXBUF];
859         char n[MAXBUF];
860         strlcpy(t,tag.c_str(),MAXBUF);
861         strlcpy(n,name.c_str(),MAXBUF);
862         int res = ReadConf(cache,t,n,index,val);
863         if (!res)
864         {
865                 this->error = CONF_VALUE_NOT_FOUND;
866                 return "";
867         }
868         return val;
869 }
870
871 bool ConfigReader::ReadFlag(std::string tag, std::string name, int index)
872 {
873         char val[MAXBUF];
874         char t[MAXBUF];
875         char n[MAXBUF];
876         strlcpy(t,tag.c_str(),MAXBUF);
877         strlcpy(n,name.c_str(),MAXBUF);
878         int res = ReadConf(cache,t,n,index,val);
879         if (!res)
880         {
881                 this->error = CONF_VALUE_NOT_FOUND;
882                 return false;
883         }
884         std::string s = val;
885         return ((s == "yes") || (s == "YES") || (s == "true") || (s == "TRUE") || (s == "1"));
886 }
887
888 long ConfigReader::ReadInteger(std::string tag, std::string name, int index, bool needs_unsigned)
889 {
890         char val[MAXBUF];
891         char t[MAXBUF];
892         char n[MAXBUF];
893         strlcpy(t,tag.c_str(),MAXBUF);
894         strlcpy(n,name.c_str(),MAXBUF);
895         int res = ReadConf(cache,t,n,index,val);
896         if (!res)
897         {
898                 this->error = CONF_VALUE_NOT_FOUND;
899                 return 0;
900         }
901         for (unsigned int i = 0; i < strlen(val); i++)
902         {
903                 if (!isdigit(val[i]))
904                 {
905                         this->error = CONF_NOT_A_NUMBER;
906                         return 0;
907                 }
908         }
909         if ((needs_unsigned) && (atoi(val)<0))
910         {
911                 this->error = CONF_NOT_UNSIGNED;
912                 return 0;
913         }
914         return atoi(val);
915 }
916
917 long ConfigReader::GetError()
918 {
919         long olderr = this->error;
920         this->error = 0;
921         return olderr;
922 }
923
924 void ConfigReader::DumpErrors(bool bail, userrec* user)
925 {
926         if (bail)
927         {
928                 printf("There were errors in your configuration:\n%s",errorlog->str().c_str());
929                 exit(0);
930         }
931         else
932         {
933                 char dataline[1024];
934                 if (user)
935                 {
936                         WriteServ(user->fd,"NOTICE %s :There were errors in the configuration file:",user->nick);
937                         while (!errorlog->eof())
938                         {
939                                 errorlog->getline(dataline,1024);
940                                 WriteServ(user->fd,"NOTICE %s :%s",user->nick,dataline);
941                         }
942                 }
943                 else
944                 {
945                         WriteOpers("There were errors in the configuration file:",user->nick);
946                         while (!errorlog->eof())
947                         {
948                                 errorlog->getline(dataline,1024);
949                                 WriteOpers(dataline);
950                         }
951                 }
952                 return;
953         }
954 }
955
956
957 int ConfigReader::Enumerate(std::string tag)
958 {
959         return EnumConf(cache,tag.c_str());
960 }
961
962 int ConfigReader::EnumerateValues(std::string tag, int index)
963 {
964         return EnumValues(cache, tag.c_str(), index);
965 }
966
967 bool ConfigReader::Verify()
968 {
969         return this->readerror;
970 }
971
972
973 FileReader::FileReader(std::string filename)
974 {
975         file_cache c;
976         readfile(c,filename.c_str());
977         this->fc = c;
978 }
979
980 FileReader::FileReader()
981 {
982 }
983
984 void FileReader::LoadFile(std::string filename)
985 {
986         file_cache c;
987         readfile(c,filename.c_str());
988         this->fc = c;
989 }
990
991
992 FileReader::~FileReader()
993 {
994 }
995
996 bool FileReader::Exists()
997 {
998         if (fc.size() == 0)
999         {
1000                 return(false);
1001         }
1002         else
1003         {
1004                 return(true);
1005         }
1006 }
1007
1008 std::string FileReader::GetLine(int x)
1009 {
1010         if ((x<0) || ((unsigned)x>fc.size()))
1011                 return "";
1012         return fc[x];
1013 }
1014
1015 int FileReader::FileSize()
1016 {
1017         return fc.size();
1018 }
1019
1020
1021 std::vector<Module*> modules(255);
1022 std::vector<ircd_module*> factory(255);
1023
1024 int MODCOUNT  = -1;
1025
1026