]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules.cpp
More stuff for allowing hostnames in <bind> and <link> again - note there is a FIXME...
[user/henk/code/inspircd.git] / src / modules.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "inspircd_config.h"
18 #include "inspircd.h"
19 #include "configreader.h"
20 #include <unistd.h>
21 #include <sys/errno.h>
22 #include <time.h>
23 #include <string>
24 #include <map>
25 #include <sstream>
26 #include <vector>
27 #include <deque>
28 #include "users.h"
29 #include "ctables.h"
30 #include "globals.h"
31 #include "modules.h"
32 #include "dynamic.h"
33 #include "wildcard.h"
34 #include "message.h"
35 #include "mode.h"
36 #include "xline.h"
37 #include "commands.h"
38 #include "inspstring.h"
39 #include "helperfuncs.h"
40 #include "hashcomp.h"
41 #include "socket.h"
42 #include "socketengine.h"
43 #include "typedefs.h"
44 #include "modules.h"
45 #include "command_parse.h"
46
47 extern ServerConfig *Config;
48 extern InspIRCd* ServerInstance;
49 extern int MODCOUNT;
50 extern ModuleList modules;
51 extern FactoryList factory;
52 extern std::vector<InspSocket*> module_sockets;
53 extern std::vector<userrec*> local_users;
54 extern time_t TIME;
55 extern userrec* fd_ref_table[MAX_DESCRIPTORS];
56 extern user_hash clientlist;
57 extern chan_hash chanlist;
58 extern command_table cmdlist;
59
60 class Server;
61
62 ExtModeList EMode;
63 featurelist Features;
64
65 // returns true if an extended mode character is in use
66 bool ModeDefined(char modechar, int type)
67 {
68         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
69         {
70                 if ((i->modechar == modechar) && (i->type == type))
71                 {
72                         return true;
73                 }
74         }
75         return false;
76 }
77
78 bool ModeIsListMode(char modechar, int type)
79 {
80         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
81         {
82                 if ((i->modechar == modechar) && (i->type == type) && (i->list == true))
83                 {
84                         return true;
85                 }
86         }
87         return false;
88 }
89
90 bool ModeDefinedOper(char modechar, int type)
91 {
92         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
93         {
94                 if ((i->modechar == modechar) && (i->type == type) && (i->needsoper == true))
95                 {
96                         return true;
97                 }
98         }
99         return false;
100 }
101
102 // returns number of parameters for a custom mode when it is switched on
103 int ModeDefinedOn(char modechar, int type)
104 {
105         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
106         {
107                 if ((i->modechar == modechar) && (i->type == type))
108                 {
109                         return i->params_when_on;
110                 }
111         }
112         return 0;
113 }
114
115 // returns number of parameters for a custom mode when it is switched on
116 int ModeDefinedOff(char modechar, int type)
117 {
118         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
119         {
120                 if ((i->modechar == modechar) && (i->type == type))
121                 {
122                         return i->params_when_off;
123                 }
124         }
125         return 0;
126 }
127
128 // returns true if an extended mode character is in use
129 bool DoAddExtendedMode(char modechar, int type, bool requires_oper, int params_on, int params_off)
130 {
131         if (ModeDefined(modechar,type)) {
132                 return false;
133         }
134         EMode.push_back(ExtMode(modechar,type,requires_oper,params_on,params_off));
135         return true;
136 }
137
138 // turns a mode into a listmode
139 void ModeMakeList(char modechar)
140 {
141         for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
142         {
143                 if ((i->modechar == modechar) && (i->type == MT_CHANNEL))
144                 {
145                         i->list = true;
146                         return;
147                 }
148         }
149         return;
150 }
151
152 // version is a simple class for holding a modules version number
153
154 Version::Version(int major, int minor, int revision, int build, int flags) : Major(major), Minor(minor), Revision(revision), Build(build), Flags(flags) { };
155
156 // admin is a simple class for holding a server's administrative info
157
158 Admin::Admin(std::string name, std::string email, std::string nick) : Name(name), Email(email), Nick(nick) { };
159
160 Request::Request(void* anydata, Module* src, Module* dst) : data(anydata), source(src), dest(dst) { };
161
162 char* Request::GetData()
163 {
164         return (char*)this->data;
165 }
166
167 Module* Request::GetSource()
168 {
169         return this->source;
170 }
171
172 Module* Request::GetDest()
173 {
174         return this->dest;
175 }
176
177 char* Request::Send()
178 {
179         if (this->dest)
180         {
181                 return dest->OnRequest(this);
182         }
183         else
184         {
185                 return NULL;
186         }
187 }
188
189 Event::Event(void* anydata, Module* src, const std::string &eventid) : data(anydata), source(src), id(eventid) { };
190
191 char* Event::GetData()
192 {
193         return (char*)this->data;
194 }
195
196 Module* Event::GetSource()
197 {
198         return this->source;
199 }
200
201 char* Event::Send()
202 {
203         FOREACH_MOD(I_OnEvent,OnEvent(this));
204         return NULL;
205 }
206
207 std::string Event::GetEventID()
208 {
209         return this->id;
210 }
211
212
213 // These declarations define the behavours of the base class Module (which does nothing at all)
214
215                 Module::Module(Server* Me) { }
216                 Module::~Module() { }
217 void            Module::OnUserConnect(userrec* user) { }
218 void            Module::OnUserQuit(userrec* user, const std::string& message) { }
219 void            Module::OnUserDisconnect(userrec* user) { }
220 void            Module::OnUserJoin(userrec* user, chanrec* channel) { }
221 void            Module::OnUserPart(userrec* user, chanrec* channel, const std::string &partmessage) { }
222 void            Module::OnRehash(const std::string &parameter) { }
223 void            Module::OnServerRaw(std::string &raw, bool inbound, userrec* user) { }
224 int             Module::OnUserPreJoin(userrec* user, chanrec* chan, const char* cname) { return 0; }
225 int             Module::OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list &params) { return false; }
226 void            Module::OnMode(userrec* user, void* dest, int target_type, const std::string &text) { };
227 Version         Module::GetVersion() { return Version(1,0,0,0,VF_VENDOR); }
228 void            Module::OnOper(userrec* user, const std::string &opertype) { };
229 void            Module::OnPostOper(userrec* user, const std::string &opertype) { };
230 void            Module::OnInfo(userrec* user) { };
231 void            Module::OnWhois(userrec* source, userrec* dest) { };
232 int             Module::OnUserPreInvite(userrec* source,userrec* dest,chanrec* channel) { return 0; };
233 int             Module::OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text,char status) { return 0; };
234 int             Module::OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text,char status) { return 0; };
235 int             Module::OnUserPreNick(userrec* user, const std::string &newnick) { return 0; };
236 void            Module::OnUserPostNick(userrec* user, const std::string &oldnick) { };
237 int             Module::OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type) { return ACR_DEFAULT; };
238 void            Module::On005Numeric(std::string &output) { };
239 int             Module::OnKill(userrec* source, userrec* dest, const std::string &reason) { return 0; };
240 void            Module::OnLoadModule(Module* mod,const std::string &name) { };
241 void            Module::OnUnloadModule(Module* mod,const std::string &name) { };
242 void            Module::OnBackgroundTimer(time_t curtime) { };
243 void            Module::OnSendList(userrec* user, chanrec* channel, char mode) { };
244 int             Module::OnPreCommand(const std::string &command, char **parameters, int pcnt, userrec *user, bool validated) { return 0; };
245 bool            Module::OnCheckReady(userrec* user) { return true; };
246 void            Module::OnUserRegister(userrec* user) { };
247 int             Module::OnUserPreKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason) { return 0; };
248 void            Module::OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason) { };
249 int             Module::OnRawMode(userrec* user, chanrec* chan, char mode, const std::string &param, bool adding, int pcnt) { return 0; };
250 int             Module::OnCheckInvite(userrec* user, chanrec* chan) { return 0; };
251 int             Module::OnCheckKey(userrec* user, chanrec* chan, const std::string &keygiven) { return 0; };
252 int             Module::OnCheckLimit(userrec* user, chanrec* chan) { return 0; };
253 int             Module::OnCheckBan(userrec* user, chanrec* chan) { return 0; };
254 int             Module::OnStats(char symbol, userrec* user) { return 0; };
255 int             Module::OnChangeLocalUserHost(userrec* user, const std::string &newhost) { return 0; };
256 int             Module::OnChangeLocalUserGECOS(userrec* user, const std::string &newhost) { return 0; };
257 int             Module::OnLocalTopicChange(userrec* user, chanrec* chan, const std::string &topic) { return 0; };
258 void            Module::OnEvent(Event* event) { return; };
259 char*           Module::OnRequest(Request* request) { return NULL; };
260 int             Module::OnOperCompare(const std::string &password, const std::string &input) { return 0; };
261 void            Module::OnGlobalOper(userrec* user) { };
262 void            Module::OnGlobalConnect(userrec* user) { };
263 int             Module::OnAddBan(userrec* source, chanrec* channel,const std::string &banmask) { return 0; };
264 int             Module::OnDelBan(userrec* source, chanrec* channel,const std::string &banmask) { return 0; };
265 void            Module::OnRawSocketAccept(int fd, const std::string &ip, int localport) { };
266 int             Module::OnRawSocketWrite(int fd, char* buffer, int count) { return 0; };
267 void            Module::OnRawSocketClose(int fd) { };
268 int             Module::OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) { return 0; };
269 void            Module::OnUserMessage(userrec* user, void* dest, int target_type, const std::string &text, char status) { };
270 void            Module::OnUserNotice(userrec* user, void* dest, int target_type, const std::string &text, char status) { };
271 void            Module::OnRemoteKill(userrec* source, userrec* dest, const std::string &reason) { };
272 void            Module::OnUserInvite(userrec* source,userrec* dest,chanrec* channel) { };
273 void            Module::OnPostLocalTopicChange(userrec* user, chanrec* chan, const std::string &topic) { };
274 void            Module::OnGetServerDescription(const std::string &servername,std::string &description) { };
275 void            Module::OnSyncUser(userrec* user, Module* proto, void* opaque) { };
276 void            Module::OnSyncChannel(chanrec* chan, Module* proto, void* opaque) { };
277 void            Module::ProtoSendMode(void* opaque, int target_type, void* target, const std::string &modeline) { };
278 void            Module::OnSyncChannelMetaData(chanrec* chan, Module* proto,void* opaque, const std::string &extname) { };
279 void            Module::OnSyncUserMetaData(userrec* user, Module* proto,void* opaque, const std::string &extname) { };
280 void            Module::OnSyncOtherMetaData(Module* proto, void* opaque) { };
281 void            Module::OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata) { };
282 void            Module::ProtoSendMetaData(void* opaque, int target_type, void* target, const std::string &extname, const std::string &extdata) { };
283 void            Module::OnWallops(userrec* user, const std::string &text) { };
284 void            Module::OnChangeHost(userrec* user, const std::string &newhost) { };
285 void            Module::OnChangeName(userrec* user, const std::string &gecos) { };
286 void            Module::OnAddGLine(long duration, userrec* source, const std::string &reason, const std::string &hostmask) { };
287 void            Module::OnAddZLine(long duration, userrec* source, const std::string &reason, const std::string &ipmask) { };
288 void            Module::OnAddKLine(long duration, userrec* source, const std::string &reason, const std::string &hostmask) { };
289 void            Module::OnAddQLine(long duration, userrec* source, const std::string &reason, const std::string &nickmask) { };
290 void            Module::OnAddELine(long duration, userrec* source, const std::string &reason, const std::string &hostmask) { };
291 void            Module::OnDelGLine(userrec* source, const std::string &hostmask) { };
292 void            Module::OnDelZLine(userrec* source, const std::string &ipmask) { };
293 void            Module::OnDelKLine(userrec* source, const std::string &hostmask) { };
294 void            Module::OnDelQLine(userrec* source, const std::string &nickmask) { };
295 void            Module::OnDelELine(userrec* source, const std::string &hostmask) { };
296 void            Module::OnCleanup(int target_type, void* item) { };
297 void            Module::Implements(char* Implements) { for (int j = 0; j < 255; j++) Implements[j] = 0; };
298 void            Module::OnChannelDelete(chanrec* chan) { };
299 Priority        Module::Prioritize() { return PRIORITY_DONTCARE; }
300 void            Module::OnSetAway(userrec* user) { };
301 void            Module::OnCancelAway(userrec* user) { };
302
303 /* server is a wrapper class that provides methods to all of the C-style
304  * exports in the core
305  */
306
307 Server::Server()
308 {
309 }
310
311 Server::~Server()
312 {
313 }
314
315 void Server::AddSocket(InspSocket* sock)
316 {
317         module_sockets.push_back(sock);
318 }
319
320 void Server::RemoveSocket(InspSocket* sock)
321 {
322         for (std::vector<InspSocket*>::iterator a = module_sockets.begin(); a < module_sockets.end(); a++)
323         {
324                 InspSocket* s = (InspSocket*)*a;
325                 if (s == sock)
326                         s->MarkAsClosed();
327         }
328 }
329
330 long Server::PriorityAfter(const std::string &modulename)
331 {
332         for (unsigned int j = 0; j < Config->module_names.size(); j++)
333         {
334                 if (Config->module_names[j] == modulename)
335                 {
336                         return ((j << 8) | PRIORITY_AFTER);
337                 }
338         }
339         return PRIORITY_DONTCARE;
340 }
341
342 long Server::PriorityBefore(const std::string &modulename)
343 {
344         for (unsigned int j = 0; j < Config->module_names.size(); j++)
345         {
346                 if (Config->module_names[j] == modulename)
347                 {
348                         return ((j << 8) | PRIORITY_BEFORE);
349                 }
350         }
351         return PRIORITY_DONTCARE;
352 }
353
354 bool Server::PublishFeature(std::string FeatureName, Module* Mod)
355 {
356         if (Features.find(FeatureName) == Features.end())
357         {
358                 Features[FeatureName] = Mod;
359                 return true;
360         }
361         return false;
362 }
363
364 bool Server::UnpublishFeature(std::string FeatureName)
365 {
366         featurelist::iterator iter = Features.find(FeatureName);
367         
368         if (iter == Features.end())
369                 return false;
370
371         Features.erase(iter);
372 }
373
374 Module* Server::FindFeature(std::string FeatureName)
375 {
376         featurelist::iterator iter = Features.find(FeatureName);
377
378         if (iter == Features.end())
379                 return NULL;
380
381         return iter->second;
382 }
383
384 void Server::RehashServer()
385 {
386         WriteOpers("*** Rehashing config file");
387         Config->Read(false,NULL);
388 }
389
390 ServerConfig* Server::GetConfig()
391 {
392         return Config;
393 }
394
395 std::string Server::GetVersion()
396 {
397         return ServerInstance->GetVersionString();
398 }
399
400 void Server::DelSocket(InspSocket* sock)
401 {
402         for (std::vector<InspSocket*>::iterator a = module_sockets.begin(); a < module_sockets.end(); a++)
403         {
404                 if (*a == sock)
405                 {
406                         module_sockets.erase(a);
407                         return;
408                 }
409         }
410 }
411
412 long Server::GetChannelCount()
413 {
414         return (long)chanlist.size();
415 }
416
417 /* This is ugly, yes, but hash_map's arent designed to be
418  * addressed in this manner, and this is a bit of a kludge.
419  * Luckily its a specialist function and rarely used by
420  * many modules (in fact, it was specially created to make
421  * m_safelist possible, initially).
422  */
423
424 chanrec* Server::GetChannelIndex(long index)
425 {
426         int target = 0;
427         for (chan_hash::iterator n = chanlist.begin(); n != chanlist.end(); n++, target++)
428         {
429                 if (index == target)
430                         return n->second;
431         }
432         return NULL;
433 }
434
435 void Server::AddTimer(InspTimer* T)
436 {
437         ::AddTimer(T);
438 }
439
440 void Server::SendOpers(const std::string &s)
441 {
442         WriteOpers("%s",s.c_str());
443 }
444
445 bool Server::MatchText(const std::string &sliteral, const std::string &spattern)
446 {
447         return match(sliteral.c_str(),spattern.c_str());
448 }
449
450 void Server::SendToModeMask(const std::string &modes, int flags, const std::string &text)
451 {
452         WriteMode(modes.c_str(),flags,"%s",text.c_str());
453 }
454
455 chanrec* Server::JoinUserToChannel(userrec* user, const std::string &cname, const std::string &key)
456 {
457         return add_channel(user,cname.c_str(),key.c_str(),false);
458 }
459
460 chanrec* Server::PartUserFromChannel(userrec* user, const std::string &cname, const std::string &reason)
461 {
462         return del_channel(user,cname.c_str(),reason.c_str(),false);
463 }
464
465 chanuserlist Server::GetUsers(chanrec* chan)
466 {
467         chanuserlist userl;
468         userl.clear();
469         CUList *list = chan->GetUsers();
470         for (CUList::iterator i = list->begin(); i != list->end(); i++)
471                 userl.push_back(i->second);
472         return userl;
473 }
474 void Server::ChangeUserNick(userrec* user, const std::string &nickname)
475 {
476         force_nickchange(user,nickname.c_str());
477 }
478
479 void Server::KickUser(userrec* source, userrec* target, chanrec* chan, const std::string &reason)
480 {
481         if (source)
482         {
483                 kick_channel(source,target,chan,(char*)reason.c_str());
484         }
485         else
486         {
487                 server_kick_channel(target,chan,(char*)reason.c_str(),true);
488         }
489 }
490
491 void Server::QuitUser(userrec* user, const std::string &reason)
492 {
493         kill_link(user,reason.c_str());
494 }
495
496 bool Server::IsUlined(const std::string &server)
497 {
498         return is_uline(server.c_str());
499 }
500
501 bool Server::CallCommandHandler(const std::string &commandname, char** parameters, int pcnt, userrec* user)
502 {
503         return ServerInstance->Parser->CallHandler(commandname,parameters,pcnt,user);
504 }
505
506 bool Server::IsValidModuleCommand(const std::string &commandname, int pcnt, userrec* user)
507 {
508         return ServerInstance->Parser->IsValidCommand(commandname, pcnt, user);
509 }
510
511 void Server::Log(int level, const std::string &s)
512 {
513         log(level,"%s",s.c_str());
514 }
515
516 void Server::AddCommand(command_t *f)
517 {
518         if (!ServerInstance->Parser->CreateCommand(f))
519         {
520                 ModuleException err("Command "+std::string(f->command)+" already exists.");
521                 throw (err);
522         }
523 }
524
525 void Server::SendMode(char **parameters, int pcnt, userrec *user)
526 {
527         ServerInstance->ModeGrok->ServerMode(parameters,pcnt,user);
528 }
529
530 void Server::Send(int Socket, const std::string &s)
531 {
532         Write_NoFormat(Socket,s.c_str());
533 }
534
535 void Server::SendServ(int Socket, const std::string &s)
536 {
537         WriteServ_NoFormat(Socket,s.c_str());
538 }
539
540 void Server::SendFrom(int Socket, userrec* User, const std::string &s)
541 {
542         WriteFrom_NoFormat(Socket,User,s.c_str());
543 }
544
545 void Server::SendTo(userrec* Source, userrec* Dest, const std::string &s)
546 {
547         if (!Source)
548         {
549                 // if source is NULL, then the message originates from the local server
550                 WriteServ_NoFormat(Dest->fd,s.c_str());
551         }
552         else
553         {
554                 // otherwise it comes from the user specified
555                 WriteTo_NoFormat(Source,Dest,s.c_str());
556         }
557 }
558
559 void Server::SendChannelServerNotice(const std::string &ServName, chanrec* Channel, const std::string &text)
560 {
561         WriteChannelWithServ_NoFormat((char*)ServName.c_str(), Channel, text.c_str());
562 }
563
564 void Server::SendChannel(userrec* User, chanrec* Channel, const std::string &s, bool IncludeSender)
565 {
566         if (IncludeSender)
567         {
568                 WriteChannel_NoFormat(Channel,User,s.c_str());
569         }
570         else
571         {
572                 ChanExceptSender_NoFormat(Channel,User,0,s.c_str());
573         }
574 }
575
576 bool Server::CommonChannels(userrec* u1, userrec* u2)
577 {
578         return (common_channels(u1,u2) != 0);
579 }
580
581 void Server::DumpText(userrec* User, const std::string &LinePrefix, stringstream &TextStream)
582 {
583         std::string CompleteLine = LinePrefix;
584         std::string Word = "";
585         while (TextStream >> Word)
586         {
587                 if (CompleteLine.length() + Word.length() + 3 > 500)
588                 {
589                         WriteServ_NoFormat(User->fd,CompleteLine.c_str());
590                         CompleteLine = LinePrefix;
591                 }
592                 CompleteLine = CompleteLine + Word + " ";
593         }
594         WriteServ_NoFormat(User->fd,CompleteLine.c_str());
595 }
596
597 void Server::SendCommon(userrec* User, const std::string &text, bool IncludeSender)
598 {
599         if (IncludeSender)
600         {
601                 WriteCommon_NoFormat(User,text.c_str());
602         }
603         else
604         {
605                 WriteCommonExcept_NoFormat(User,text.c_str());
606         }
607 }
608
609 void Server::SendWallops(userrec* User, const std::string &text)
610 {
611         WriteWallOps(User,false,"%s",text.c_str());
612 }
613
614 void Server::ChangeHost(userrec* user, const std::string &host)
615 {
616         ChangeDisplayedHost(user,host.c_str());
617 }
618
619 void Server::ChangeGECOS(userrec* user, const std::string &gecos)
620 {
621         ChangeName(user,gecos.c_str());
622 }
623
624 bool Server::IsNick(const std::string &nick)
625 {
626         return (isnick(nick.c_str()) != 0);
627 }
628
629 userrec* Server::FindNick(const std::string &nick)
630 {
631         return Find(nick);
632 }
633
634 userrec* Server::FindDescriptor(int socket)
635 {
636         return (socket < 65536 ? fd_ref_table[socket] : NULL);
637 }
638
639 chanrec* Server::FindChannel(const std::string &channel)
640 {
641         return FindChan(channel.c_str());
642 }
643
644 std::string Server::ChanMode(userrec* User, chanrec* Chan)
645 {
646         return cmode(User,Chan);
647 }
648
649 std::string Server::GetServerName()
650 {
651         return Config->ServerName;
652 }
653
654 std::string Server::GetNetworkName()
655 {
656         return Config->Network;
657 }
658
659 std::string Server::GetServerDescription()
660 {
661         return Config->ServerDesc;
662 }
663
664 Admin Server::GetAdmin()
665 {
666         return Admin(Config->AdminName,Config->AdminEmail,Config->AdminNick);
667 }
668
669
670
671 bool Server::AddExtendedMode(char modechar, int type, bool requires_oper, int params_when_on, int params_when_off)
672 {
673         if (((modechar >= 'A') && (modechar <= 'Z')) || ((modechar >= 'a') && (modechar <= 'z')))
674         {
675                 if (type == MT_SERVER)
676                 {
677                         ModuleException e("Modes of type MT_SERVER are reserved for future expansion");
678                         throw(e);
679                         return false;
680                 }
681                 if (((params_when_on>0) || (params_when_off>0)) && (type == MT_CLIENT))
682                 {
683                         ModuleException e("Parameters on MT_CLIENT modes are not supported");
684                         throw(e);
685                         return false;
686                 }
687                 if ((params_when_on>1) || (params_when_off>1))
688                 {
689                         ModuleException e("More than one parameter for an MT_CHANNEL mode is not yet supported");
690                         throw(e);
691                         return false;
692                 }
693                 return DoAddExtendedMode(modechar,type,requires_oper,params_when_on,params_when_off);
694         }
695         else
696         {
697                 ModuleException e("Muppet modechar detected.");
698                 throw(e);
699         }
700         return false;
701 }
702
703 bool Server::AddExtendedListMode(char modechar)
704 {
705         bool res = DoAddExtendedMode(modechar,MT_CHANNEL,false,1,1);
706         if (res)
707                 ModeMakeList(modechar);
708         return res;
709 }
710
711 int Server::CountUsers(chanrec* c)
712 {
713         return usercount(c);
714 }
715
716
717 bool Server::UserToPseudo(userrec* user, const std::string &message)
718 {
719         unsigned int old_fd = user->fd;
720         Write(old_fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,message.c_str());
721         user->FlushWriteBuf();
722         user->ClearBuffer();
723         user->fd = FD_MAGIC_NUMBER;
724
725         if (find(local_users.begin(),local_users.end(),user) != local_users.end())
726         {
727                 local_users.erase(find(local_users.begin(),local_users.end(),user));
728                 log(DEBUG,"Delete local user");
729         }
730
731         ServerInstance->SE->DelFd(old_fd);
732         shutdown(old_fd,2);
733         close(old_fd);
734         return true;
735 }
736
737 bool Server::PseudoToUser(userrec* alive, userrec* zombie, const std::string &message)
738 {
739         log(DEBUG,"PseudoToUser");
740         zombie->fd = alive->fd;
741         FOREACH_MOD(I_OnUserQuit,OnUserQuit(alive,message));
742         alive->fd = FD_MAGIC_NUMBER;
743         alive->FlushWriteBuf();
744         alive->ClearBuffer();
745         // save these for later
746         std::string oldnick = alive->nick;
747         std::string oldhost = alive->host;
748         std::string oldident = alive->ident;
749         kill_link(alive,message.c_str());
750         if (find(local_users.begin(),local_users.end(),alive) != local_users.end())
751         {
752                 local_users.erase(find(local_users.begin(),local_users.end(),alive));
753                 log(DEBUG,"Delete local user");
754         }
755         // Fix by brain - cant write the user until their fd table entry is updated
756         fd_ref_table[zombie->fd] = zombie;
757         Write(zombie->fd,":%s!%s@%s NICK %s",oldnick.c_str(),oldident.c_str(),oldhost.c_str(),zombie->nick);
758         for (std::vector<ucrec*>::const_iterator i = zombie->chans.begin(); i != zombie->chans.end(); i++)
759         {
760                 if (((ucrec*)(*i))->channel != NULL)
761                 {
762                                 chanrec* Ptr = ((ucrec*)(*i))->channel;
763                                 WriteFrom(zombie->fd,zombie,"JOIN %s",Ptr->name);
764                                 if (Ptr->topicset)
765                                 {
766                                         WriteServ(zombie->fd,"332 %s %s :%s", zombie->nick, Ptr->name, Ptr->topic);
767                                         WriteServ(zombie->fd,"333 %s %s %s %d", zombie->nick, Ptr->name, Ptr->setby, Ptr->topicset);
768                                 }
769                                 userlist(zombie,Ptr);
770                                 WriteServ(zombie->fd,"366 %s %s :End of /NAMES list.", zombie->nick, Ptr->name);
771                 }
772         }
773         if ((find(local_users.begin(),local_users.end(),zombie) == local_users.end()) && (zombie->fd != FD_MAGIC_NUMBER))
774                 local_users.push_back(zombie);
775
776         return true;
777 }
778
779 void Server::AddGLine(long duration, const std::string &source, const std::string &reason, const std::string &hostmask)
780 {
781         add_gline(duration, source.c_str(), reason.c_str(), hostmask.c_str());
782 }
783
784 void Server::AddQLine(long duration, const std::string &source, const std::string &reason, const std::string &nickname)
785 {
786         add_qline(duration, source.c_str(), reason.c_str(), nickname.c_str());
787 }
788
789 void Server::AddZLine(long duration, const std::string &source, const std::string &reason, const std::string &ipaddr)
790 {
791         add_zline(duration, source.c_str(), reason.c_str(), ipaddr.c_str());
792 }
793
794 void Server::AddKLine(long duration, const std::string &source, const std::string &reason, const std::string &hostmask)
795 {
796         add_kline(duration, source.c_str(), reason.c_str(), hostmask.c_str());
797 }
798
799 void Server::AddELine(long duration, const std::string &source, const std::string &reason, const std::string &hostmask)
800 {
801         add_eline(duration, source.c_str(), reason.c_str(), hostmask.c_str());
802 }
803
804 bool Server::DelGLine(const std::string &hostmask)
805 {
806         return del_gline(hostmask.c_str());
807 }
808
809 bool Server::DelQLine(const std::string &nickname)
810 {
811         return del_qline(nickname.c_str());
812 }
813
814 bool Server::DelZLine(const std::string &ipaddr)
815 {
816         return del_zline(ipaddr.c_str());
817 }
818
819 bool Server::DelKLine(const std::string &hostmask)
820 {
821         return del_kline(hostmask.c_str());
822 }
823
824 bool Server::DelELine(const std::string &hostmask)
825 {
826         return del_eline(hostmask.c_str());
827 }
828
829 long Server::CalcDuration(const std::string &delta)
830 {
831         return duration(delta.c_str());
832 }
833
834 /*
835  * XXX why on *earth* is this in modules.cpp...? I think
836  * perhaps we need a server.cpp for Server:: stuff where possible. -- w00t
837  */
838 bool Server::IsValidMask(const std::string &mask)
839 {
840         char* dest = (char*)mask.c_str();
841         if (strchr(dest,'!')==0)
842                 return false;
843         if (strchr(dest,'@')==0)
844                 return false;
845         for (char* i = dest; *i; i++)
846                 if (*i < 32)
847                         return false;
848         for (char* i = dest; *i; i++)
849                 if (*i > 126)
850                         return false;
851         unsigned int c = 0;
852         for (char* i = dest; *i; i++)
853                 if (*i == '!')
854                         c++;
855         if (c>1)
856                 return false;
857         c = 0;
858         for (char* i = dest; *i; i++)
859                 if (*i == '@')
860                         c++;
861         if (c>1)
862                 return false;
863
864         return true;
865 }
866
867 Module* Server::FindModule(const std::string &name)
868 {
869         for (int i = 0; i <= MODCOUNT; i++)
870         {
871                 if (Config->module_names[i] == name)
872                 {
873                         return modules[i];
874                 }
875         }
876         return NULL;
877 }
878
879 ConfigReader::ConfigReader()
880 {
881         // Config->ClearStack();
882         
883         /* Is there any reason to load the entire config file again here?
884          * it's needed if they specify another config file, but using the
885          * default one we can just use the global config data - pre-parsed!
886          */
887         //~ this->cache = new std::stringstream(std::stringstream::in | std::stringstream::out);
888         this->errorlog = new std::ostringstream(std::stringstream::in | std::stringstream::out);
889         
890         //~ this->readerror = Config->LoadConf(CONFIG_FILE, this->cache,this->errorlog);
891         //~ if (!this->readerror)
892                 //~ this->error = CONF_FILE_NOT_FOUND;
893         
894         this->data = &Config->config_data;
895         this->privatehash = false;
896 }
897
898
899 ConfigReader::~ConfigReader()
900 {
901         //~ if (this->cache)
902                 //~ delete this->cache;
903         if (this->errorlog)
904                 DELETE(this->errorlog);
905         if(this->privatehash)
906                 DELETE(this->data);
907 }
908
909
910 ConfigReader::ConfigReader(const std::string &filename)
911 {
912         Config->ClearStack();
913         
914         this->data = new ConfigDataHash;
915         this->privatehash = true;
916         this->errorlog = new std::ostringstream(std::stringstream::in | std::stringstream::out);
917         this->readerror = Config->LoadConf(*this->data, filename, *this->errorlog);
918         if (!this->readerror)
919                 this->error = CONF_FILE_NOT_FOUND;
920 };
921
922 std::string ConfigReader::ReadValue(const std::string &tag, const std::string &name, int index)
923 {
924         /* Don't need to strlcpy() tag and name anymore, ReadConf() takes const char* */ 
925         std::string result;
926         
927         if (!Config->ConfValue(*this->data, tag, name, index, result))
928         {
929                 this->error = CONF_VALUE_NOT_FOUND;
930                 return "";
931         }
932         
933         return result;
934 }
935
936 bool ConfigReader::ReadFlag(const std::string &tag, const std::string &name, int index)
937 {
938         return Config->ConfValueBool(*this->data, tag, name, index);
939 }
940
941 long ConfigReader::ReadInteger(const std::string &tag, const std::string &name, int index, bool needs_unsigned)
942 {
943         int result;
944         
945         if(!Config->ConfValueInteger(*this->data, tag, name, index, result))
946         {
947                 this->error = CONF_VALUE_NOT_FOUND;
948                 return 0;
949         }
950         
951         if ((needs_unsigned) && (result < 0))
952         {
953                 this->error = CONF_NOT_UNSIGNED;
954                 return 0;
955         }
956         
957         return result;
958 }
959
960 long ConfigReader::GetError()
961 {
962         long olderr = this->error;
963         this->error = 0;
964         return olderr;
965 }
966
967 void ConfigReader::DumpErrors(bool bail, userrec* user)
968 {
969         /* XXX - Duplicated code */
970         
971         if (bail)
972         {
973                 printf("There were errors in your configuration:\n%s", this->errorlog->str().c_str());
974                 Exit(0);
975         }
976         else
977         {
978                 std::string errors = this->errorlog->str();
979                 std::string::size_type start;
980                 unsigned int prefixlen;
981                 
982                 start = 0;
983                 /* ":Config->ServerName NOTICE user->nick :" */
984                 prefixlen = strlen(Config->ServerName) + strlen(user->nick) + 11;
985         
986                 if (user)
987                 {
988                         WriteServ(user->fd,"NOTICE %s :There were errors in the configuration file:",user->nick);
989                         
990                         while(start < errors.length())
991                         {
992                                 WriteServ(user->fd, "NOTICE %s :%s",user->nick, errors.substr(start, 510 - prefixlen).c_str());
993                                 start += 510 - prefixlen;
994                         }
995                 }
996                 else
997                 {
998                         WriteOpers("There were errors in the configuration file:");
999                         
1000                         while(start < errors.length())
1001                         {
1002                                 WriteOpers(errors.substr(start, 360).c_str());
1003                                 start += 360;
1004                         }
1005                 }
1006
1007                 return;
1008         }
1009 }
1010
1011
1012 int ConfigReader::Enumerate(const std::string &tag)
1013 {
1014         return Config->ConfValueEnum(*this->data, tag);
1015 }
1016
1017 int ConfigReader::EnumerateValues(const std::string &tag, int index)
1018 {
1019         return Config->ConfVarEnum(*this->data, tag, index);
1020 }
1021
1022 bool ConfigReader::Verify()
1023 {
1024         return this->readerror;
1025 }
1026
1027
1028 FileReader::FileReader(const std::string &filename)
1029 {
1030         file_cache c;
1031         readfile(c,filename.c_str());
1032         this->fc = c;
1033 }
1034
1035 FileReader::FileReader()
1036 {
1037 }
1038
1039 void FileReader::LoadFile(const std::string &filename)
1040 {
1041         file_cache c;
1042         readfile(c,filename.c_str());
1043         this->fc = c;
1044 }
1045
1046
1047 FileReader::~FileReader()
1048 {
1049 }
1050
1051 bool FileReader::Exists()
1052 {
1053         return (!(fc.size() == 0));
1054 }
1055
1056 std::string FileReader::GetLine(int x)
1057 {
1058         if ((x<0) || ((unsigned)x>fc.size()))
1059                 return "";
1060         return fc[x];
1061 }
1062
1063 int FileReader::FileSize()
1064 {
1065         return fc.size();
1066 }
1067
1068
1069 std::vector<Module*> modules(255);
1070 std::vector<ircd_module*> factory(255);
1071
1072 int MODCOUNT  = -1;