1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
19 #include "inspircd_config.h"
21 #include "inspircd_io.h"
24 #include <sys/errno.h>
28 #include <ext/hash_map>
36 #include "connection.h"
47 #include "inspstring.h"
48 #include "helperfuncs.h"
53 extern std::vector<Module*> modules;
54 extern ServerConfig *Config;
55 extern InspIRCd* ServerInstance;
57 extern char lowermap[255];
58 static char list[MAXBUF];
59 extern userrec* fd_ref_table[MAX_DESCRIPTORS];
60 static char already_sent[MAX_DESCRIPTORS];
61 extern std::vector<userrec*> all_opers;
62 extern user_hash clientlist;
63 extern chan_hash chanlist;
65 extern std::vector<userrec*> local_users;
67 static char TIMESTR[26];
68 static time_t LAST = 0;
71 * Write a line of text `text' to the logfile (and stdout, if in nofork) if the level `level'
72 * is greater than the configured loglevel.
74 void log(int level, char *text, ...)
78 if (level < Config->LogLevel)
81 char textbuffer[MAXBUF];
85 timeinfo = localtime(&TIME);
86 strlcpy(TIMESTR,asctime(timeinfo),26);
93 va_start (argsPtr, text);
94 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
98 fprintf(Config->log_file,"%s %s\n",TIMESTR,textbuffer);
101 // nofork enabled? display it on terminal too
102 printf("%s %s\n",TIMESTR,textbuffer);
108 * Read the contents of a file located by `fname' into a file_cache pointed at by `F'.
110 * XXX - we may want to consider returning a file_cache or pointer to one, less confusing.
112 void readfile(file_cache &F, const char* fname)
115 char linebuf[MAXBUF];
117 log(DEBUG,"readfile: loading %s",fname);
119 file = fopen(fname,"r");
124 fgets(linebuf,sizeof(linebuf),file);
125 linebuf[strlen(linebuf)-1]='\0';
132 F.push_back(linebuf);
139 log(DEBUG,"readfile: failed to load file: %s",fname);
141 log(DEBUG,"readfile: loaded %s, %lu lines",fname,(unsigned long)F.size());
145 * Writes a given string in `text' to the socket on fd `sock' - only if the socket
146 * is a valid entry in the local FD table.
148 void Write_NoFormat(int sock, const char *text)
150 if ((sock < 0) || (!text) || (sock > MAX_DESCRIPTORS))
154 int bytes = snprintf(tb,MAXBUF,"%s\r\n",text);
156 if (fd_ref_table[sock])
158 if (Config->GetIOHook(fd_ref_table[sock]->port))
162 Config->GetIOHook(fd_ref_table[sock]->port)->OnRawSocketWrite(sock,tb,bytes);
164 catch (ModuleException& modexcept)
166 log(DEBUG,"Module exception caught: %s",modexcept.GetReason());
171 fd_ref_table[sock]->AddWriteBuf(tb);
173 ServerInstance->stats->statsSent += bytes;
175 else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
179 * Same as Write_NoFormat(), but formatted printf() style first.
181 void Write(int sock, char *text, ...)
183 if ((sock < 0) || (sock > MAX_DESCRIPTORS))
187 log(DEFAULT,"*** BUG *** Write was given an invalid parameter");
191 char textbuffer[MAXBUF],tb[MAXBUF];
192 va_start (argsPtr, text);
193 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
195 int bytes = snprintf(tb,MAXBUF,"%s\r\n",textbuffer);
197 if (fd_ref_table[sock])
199 if (Config->GetIOHook(fd_ref_table[sock]->port))
203 Config->GetIOHook(fd_ref_table[sock]->port)->OnRawSocketWrite(sock,tb,bytes);
205 catch (ModuleException& modexcept)
207 log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
212 fd_ref_table[sock]->AddWriteBuf(tb);
214 ServerInstance->stats->statsSent += bytes;
216 else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
219 /** WriteServ_NoFormat()
220 * Same as Write_NoFormat(), except prefixes `text' with `:server.name '.
222 void WriteServ_NoFormat(int sock, const char* text)
224 if ((sock < 0) || (!text) || (sock > MAX_DESCRIPTORS))
227 int bytes = snprintf(tb,MAXBUF,":%s %s\r\n",Config->ServerName,text);
229 if (fd_ref_table[sock])
231 if (Config->GetIOHook(fd_ref_table[sock]->port))
235 Config->GetIOHook(fd_ref_table[sock]->port)->OnRawSocketWrite(sock,tb,bytes);
237 catch (ModuleException& modexcept)
239 log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
244 fd_ref_table[sock]->AddWriteBuf(tb);
246 ServerInstance->stats->statsSent += bytes;
248 else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
252 * Same as Write(), except `text' is prefixed with `:server.name '.
254 void WriteServ(int sock, char* text, ...)
256 if ((sock < 0) || (sock > MAX_DESCRIPTORS))
260 log(DEFAULT,"*** BUG *** WriteServ was given an invalid parameter");
264 va_start (argsPtr, text);
265 char textbuffer[MAXBUF],tb[MAXBUF];
266 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
268 int bytes = snprintf(tb,MAXBUF,":%s %s\r\n",Config->ServerName,textbuffer);
270 if (fd_ref_table[sock])
272 if (Config->GetIOHook(fd_ref_table[sock]->port))
276 Config->GetIOHook(fd_ref_table[sock]->port)->OnRawSocketWrite(sock,tb,bytes);
278 catch (ModuleException& modexcept)
280 log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
285 fd_ref_table[sock]->AddWriteBuf(tb);
287 ServerInstance->stats->statsSent += bytes;
289 else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
292 /** WriteFrom_NoFormat()
293 * Write `text' to a socket with fd `sock' prefixed with `:n!u@h' - taken from
294 * the nick, user, and host of `user'.
296 void WriteFrom_NoFormat(int sock, userrec *user, const char* text)
298 if ((sock < 0) || (!text) || (!user) || (sock > MAX_DESCRIPTORS))
301 int bytes = snprintf(tb,MAXBUF,":%s %s\r\n",user->GetFullHost(),text);
303 if (fd_ref_table[sock])
305 if (Config->GetIOHook(fd_ref_table[sock]->port))
309 Config->GetIOHook(fd_ref_table[sock]->port)->OnRawSocketWrite(sock,tb,bytes);
311 catch (ModuleException& modexcept)
313 log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
318 fd_ref_table[sock]->AddWriteBuf(tb);
320 ServerInstance->stats->statsSent += bytes;
322 else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
325 /* write text from an originating user to originating user */
327 void WriteFrom(int sock, userrec *user,char* text, ...)
329 if ((sock < 0) || (sock > MAX_DESCRIPTORS))
331 if ((!text) || (!user))
333 log(DEFAULT,"*** BUG *** WriteFrom was given an invalid parameter");
337 va_start (argsPtr, text);
338 char textbuffer[MAXBUF],tb[MAXBUF];
339 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
341 int bytes = snprintf(tb,MAXBUF,":%s %s\r\n",user->GetFullHost(),textbuffer);
343 if (fd_ref_table[sock])
345 if (Config->GetIOHook(fd_ref_table[sock]->port))
349 Config->GetIOHook(fd_ref_table[sock]->port)->OnRawSocketWrite(sock,tb,bytes);
351 catch (ModuleException& modexcept)
353 log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
358 fd_ref_table[sock]->AddWriteBuf(tb);
360 ServerInstance->stats->statsSent += bytes;
362 else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
365 /* write text to an destination user from a source user (e.g. user privmsg) */
367 void WriteTo(userrec *source, userrec *dest,char *data, ...)
369 if ((!dest) || (!data))
371 log(DEFAULT,"*** BUG *** WriteTo was given an invalid parameter");
376 char textbuffer[MAXBUF];
378 va_start (argsPtr, data);
379 vsnprintf(textbuffer, MAXBUF, data, argsPtr);
383 // if no source given send it from the server.
386 WriteServ_NoFormat(dest->fd,textbuffer);
390 WriteFrom_NoFormat(dest->fd,source,textbuffer);
394 void WriteTo_NoFormat(userrec *source, userrec *dest, const char *data)
396 if ((!dest) || (!data))
400 WriteServ_NoFormat(dest->fd,data);
404 WriteFrom_NoFormat(dest->fd,source,data);
408 /* write formatted text from a source user to all users on a channel
409 * including the sender (NOT for privmsg, notice etc!) */
411 void WriteChannel(chanrec* Ptr, userrec* user, char* text, ...)
413 if ((!Ptr) || (!user) || (!text))
415 log(DEFAULT,"*** BUG *** WriteChannel was given an invalid parameter");
418 char textbuffer[MAXBUF];
420 va_start (argsPtr, text);
421 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
424 std::map<char*,char*> *ulist= Ptr->GetUsers();
425 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
428 userrec* otheruser = (userrec*)o;
429 if (otheruser->fd != FD_MAGIC_NUMBER)
430 WriteTo_NoFormat(user,otheruser,textbuffer);
434 void WriteChannel_NoFormat(chanrec* Ptr, userrec* user, const char* text)
436 if ((!Ptr) || (!user) || (!text))
438 log(DEFAULT,"*** BUG *** WriteChannel was given an invalid parameter");
441 std::map<char*,char*> *ulist= Ptr->GetUsers();
442 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
445 userrec* otheruser = (userrec*)o;
446 if (otheruser->fd != FD_MAGIC_NUMBER)
447 WriteTo_NoFormat(user,otheruser,text);
452 /* write formatted text from a source user to all users on a channel
453 * including the sender (NOT for privmsg, notice etc!) doesnt send to
454 * users on remote servers */
456 void WriteChannelLocal(chanrec* Ptr, userrec* user, char* text, ...)
458 if ((!Ptr) || (!text))
460 log(DEFAULT,"*** BUG *** WriteChannel was given an invalid parameter");
463 char textbuffer[MAXBUF];
465 va_start (argsPtr, text);
466 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
469 std::map<char*,char*> *ulist= Ptr->GetUsers();
470 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
473 userrec* otheruser = (userrec*)o;
474 if ((otheruser->fd != FD_MAGIC_NUMBER) && (otheruser != user))
478 WriteServ_NoFormat(otheruser->fd,textbuffer);
482 WriteTo_NoFormat(user,otheruser,textbuffer);
488 void WriteChannelLocal_NoFormat(chanrec* Ptr, userrec* user, const char* text)
490 if ((!Ptr) || (!text))
492 log(DEFAULT,"*** BUG *** WriteChannel was given an invalid parameter");
495 std::map<char*,char*> *ulist= Ptr->GetUsers();
496 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
499 userrec* otheruser = (userrec*)o;
500 if ((otheruser->fd != FD_MAGIC_NUMBER) && (otheruser != user))
504 WriteServ_NoFormat(otheruser->fd,text);
508 WriteTo_NoFormat(user,otheruser,text);
516 void WriteChannelWithServ(char* ServName, chanrec* Ptr, char* text, ...)
518 if ((!Ptr) || (!text))
520 log(DEFAULT,"*** BUG *** WriteChannelWithServ was given an invalid parameter");
523 char textbuffer[MAXBUF];
525 va_start (argsPtr, text);
526 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
530 std::map<char*,char*> *ulist= Ptr->GetUsers();
531 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
534 userrec* otheruser = (userrec*)o;
535 if (IS_LOCAL(otheruser))
536 WriteServ_NoFormat(otheruser->fd,textbuffer);
540 void WriteChannelWithServ_NoFormat(char* ServName, chanrec* Ptr, const char* text)
542 if ((!Ptr) || (!text))
544 log(DEFAULT,"*** BUG *** WriteChannelWithServ was given an invalid parameter");
547 std::map<char*,char*> *ulist= Ptr->GetUsers();
548 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
551 userrec* otheruser = (userrec*)o;
552 if (IS_LOCAL(otheruser))
553 WriteServ_NoFormat(otheruser->fd,text);
559 /* write formatted text from a source user to all users on a channel except
560 * for the sender (for privmsg etc) */
562 void ChanExceptSender(chanrec* Ptr, userrec* user, char status, char* text, ...)
564 if ((!Ptr) || (!user) || (!text))
566 log(DEFAULT,"*** BUG *** ChanExceptSender was given an invalid parameter");
569 char textbuffer[MAXBUF];
571 va_start (argsPtr, text);
572 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
575 std::map<char*,char*> *ulist;
579 ulist = Ptr->GetOppedUsers();
582 ulist = Ptr->GetHalfoppedUsers();
585 ulist = Ptr->GetVoicedUsers();
588 ulist = Ptr->GetUsers();
591 log(DEBUG,"%d users to write to",ulist->size());
592 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
595 userrec* otheruser = (userrec*)o;
596 if ((IS_LOCAL(otheruser)) && (user != otheruser))
597 WriteFrom_NoFormat(otheruser->fd,user,textbuffer);
601 void ChanExceptSender_NoFormat(chanrec* Ptr, userrec* user, char status, const char* text)
603 if ((!Ptr) || (!user) || (!text))
605 log(DEFAULT,"*** BUG *** ChanExceptSender was given an invalid parameter");
608 std::map<char*,char*> *ulist;
612 ulist = Ptr->GetOppedUsers();
615 ulist = Ptr->GetHalfoppedUsers();
618 ulist = Ptr->GetVoicedUsers();
621 ulist = Ptr->GetUsers();
624 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
627 userrec* otheruser = (userrec*)o;
628 if ((IS_LOCAL(otheruser)) && (user != otheruser))
629 WriteFrom_NoFormat(otheruser->fd,user,text);
633 std::string GetServerDescription(char* servername)
635 std::string description = "";
636 FOREACH_MOD(I_OnGetServerDescription,OnGetServerDescription(servername,description));
637 if (description != "")
643 return Config->ServerDesc; // not a remote server that can be found, it must be me.
647 /* write a formatted string to all users who share at least one common
648 * channel, including the source user e.g. for use in NICK */
650 void WriteCommon(userrec *u, char* text, ...)
654 log(DEFAULT,"*** BUG *** WriteCommon was given an invalid parameter");
658 if (u->registered != 7) {
659 log(DEFAULT,"*** BUG *** WriteCommon on an unregistered user");
663 char textbuffer[MAXBUF];
665 va_start (argsPtr, text);
666 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
669 // FIX: Stops a message going to the same person more than once
670 memset(&already_sent,0,MAX_DESCRIPTORS);
672 bool sent_to_at_least_one = false;
674 unsigned int y = u->chans.size();
675 for (unsigned int i = 0; i < y; i++)
677 if (u->chans[i].channel)
679 std::map<char*,char*> *ulist= u->chans[i].channel->GetUsers();
680 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
683 userrec* otheruser = (userrec*)o;
684 if ((otheruser->fd > -1) && (!already_sent[otheruser->fd]))
686 already_sent[otheruser->fd] = 1;
687 WriteFrom_NoFormat(otheruser->fd,u,textbuffer);
688 sent_to_at_least_one = true;
693 // if the user was not in any channels, no users will receive the text. Make sure the user
694 // receives their OWN message for WriteCommon
695 if (!sent_to_at_least_one)
697 WriteFrom_NoFormat(u->fd,u,textbuffer);
701 void WriteCommon_NoFormat(userrec *u, const char* text)
705 log(DEFAULT,"*** BUG *** WriteCommon was given an invalid parameter");
709 if (u->registered != 7) {
710 log(DEFAULT,"*** BUG *** WriteCommon on an unregistered user");
713 // FIX: Stops a message going to the same person more than once
714 memset(&already_sent,0,MAX_DESCRIPTORS);
716 bool sent_to_at_least_one = false;
718 unsigned int y = u->chans.size();
719 for (unsigned int i = 0; i < y; i++)
721 if (u->chans[i].channel)
723 std::map<char*,char*> *ulist= u->chans[i].channel->GetUsers();
724 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
727 userrec* otheruser = (userrec*)o;
728 if ((otheruser->fd > -1) && (!already_sent[otheruser->fd]))
730 already_sent[otheruser->fd] = 1;
731 WriteFrom_NoFormat(otheruser->fd,u,text);
732 sent_to_at_least_one = true;
737 // if the user was not in any channels, no users will receive the text. Make sure the user
738 // receives their OWN message for WriteCommon
739 if (!sent_to_at_least_one)
741 WriteFrom_NoFormat(u->fd,u,text);
746 /* write a formatted string to all users who share at least one common
747 * channel, NOT including the source user e.g. for use in QUIT */
749 void WriteCommonExcept(userrec *u, char* text, ...)
753 log(DEFAULT,"*** BUG *** WriteCommon was given an invalid parameter");
757 if (u->registered != 7) {
758 log(DEFAULT,"*** BUG *** WriteCommon on an unregistered user");
762 char textbuffer[MAXBUF];
763 char oper_quit[MAXBUF];
764 bool quit_munge = false;
767 va_start (argsPtr, text);
768 int total = vsnprintf(textbuffer, MAXBUF, text, argsPtr);
771 if ((Config->HideSplits) && (total > 6))
773 /* Yeah yeah, this is ugly. But its fast, live with it. */
774 char* check = textbuffer;
775 if ((*check++ == 'Q') && (*check++ == 'U') && (*check++ == 'I') && (*check++ == 'T') && (*check++ == ' ') && (*check++ == ':'))
777 std::stringstream split(check);
778 std::string server_one;
779 std::string server_two;
782 if ((FindServerName(server_one)) && (FindServerName(server_two)))
784 strlcpy(oper_quit,textbuffer,MAXQUIT);
785 strlcpy(check,"*.net *.split",MAXQUIT);
790 if ((Config->HideBans) && (total > 13) && (!quit_munge))
792 char* check = textbuffer;
793 if ((*check++ == 'Q') && (*check++ == 'U') && (*check++ == 'I') && (*check++ == 'T') && (*check++ == ' ') && (*check++ == ':'))
796 if ((*check++ == '-') && (*check++ == 'L') && (*check++ == 'i') && (*check++ == 'n') && (*check++ == 'e') && (*check++ == 'd') && (*check++ == ':'))
798 strlcpy(oper_quit,textbuffer,MAXQUIT);
799 *(--check) = 0; // We don't need to strlcpy, we just chop it from the :
805 memset(&already_sent,0,MAX_DESCRIPTORS);
807 unsigned int y = u->chans.size();
808 for (unsigned int i = 0; i < y; i++)
810 if (u->chans[i].channel)
812 std::map<char*,char*> *ulist= u->chans[i].channel->GetUsers();
813 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
816 userrec* otheruser = (userrec*)o;
819 if ((otheruser->fd > -1) && (!already_sent[otheruser->fd]))
821 already_sent[otheruser->fd] = 1;
824 WriteFrom_NoFormat(otheruser->fd,u,*otheruser->oper ? oper_quit : textbuffer);
826 else WriteFrom_NoFormat(otheruser->fd,u,textbuffer);
834 void WriteCommonExcept_NoFormat(userrec *u, const char* text)
838 log(DEFAULT,"*** BUG *** WriteCommon was given an invalid parameter");
842 if (u->registered != 7) {
843 log(DEFAULT,"*** BUG *** WriteCommon on an unregistered user");
847 memset(&already_sent,0,MAX_DESCRIPTORS);
849 unsigned int y = u->chans.size();
850 for (unsigned int i = 0; i < y; i++)
852 if (u->chans[i].channel)
854 std::map<char*,char*> *ulist= u->chans[i].channel->GetUsers();
855 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
858 userrec* otheruser = (userrec*)o;
861 if ((otheruser->fd > -1) && (!already_sent[otheruser->fd]))
863 already_sent[otheruser->fd] = 1;
864 WriteFrom_NoFormat(otheruser->fd,u,text);
874 void WriteOpers(char* text, ...)
878 log(DEFAULT,"*** BUG *** WriteOpers was given an invalid parameter");
882 char textbuffer[MAXBUF];
884 va_start (argsPtr, text);
885 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
888 for (std::vector<userrec*>::iterator i = all_opers.begin(); i != all_opers.end(); i++)
893 if (strchr(a->modes,'s'))
895 // send server notices to all with +s
896 WriteServ(a->fd,"NOTICE %s :%s",a->nick,textbuffer);
902 void ServerNoticeAll(char* text, ...)
907 char textbuffer[MAXBUF];
909 va_start (argsPtr, text);
910 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
913 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
915 userrec* t = (userrec*)(*i);
916 WriteServ(t->fd,"NOTICE $%s :%s",Config->ServerName,textbuffer);
920 void ServerPrivmsgAll(char* text, ...)
925 char textbuffer[MAXBUF];
927 va_start (argsPtr, text);
928 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
931 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
933 userrec* t = (userrec*)(*i);
934 WriteServ(t->fd,"PRIVMSG $%s :%s",Config->ServerName,textbuffer);
938 void WriteMode(const char* modes, int flags, const char* text, ...)
940 if ((!text) || (!modes) || (!flags))
942 log(DEFAULT,"*** BUG *** WriteMode was given an invalid parameter");
946 char textbuffer[MAXBUF];
948 va_start (argsPtr, text);
949 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
951 int modelen = strlen(modes);
953 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
955 userrec* t = (userrec*)(*i);
956 bool send_to_user = false;
960 for (int n = 0; n < modelen; n++)
962 if (!hasumode(t,modes[n]))
964 send_to_user = false;
969 else if (flags == WM_OR)
971 send_to_user = false;
972 for (int n = 0; n < modelen; n++)
974 if (hasumode(t,modes[n]))
983 WriteServ(t->fd,"NOTICE %s :%s",t->nick,textbuffer);
988 void NoticeAll(userrec *source, bool local_only, char* text, ...)
990 if ((!text) || (!source))
992 log(DEFAULT,"*** BUG *** NoticeAll was given an invalid parameter");
996 char textbuffer[MAXBUF];
998 va_start (argsPtr, text);
999 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
1002 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
1004 userrec* t = (userrec*)(*i);
1005 WriteFrom(t->fd,source,"NOTICE $* :%s",textbuffer);
1011 void WriteWallOps(userrec *source, bool local_only, char* text, ...)
1013 if ((!text) || (!source))
1015 log(DEFAULT,"*** BUG *** WriteOpers was given an invalid parameter");
1019 char textbuffer[MAXBUF];
1021 va_start (argsPtr, text);
1022 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
1025 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
1027 userrec* t = (userrec*)(*i);
1028 if ((IS_LOCAL(t)) && (strchr(t->modes,'w')))
1030 WriteTo(source,t,"WALLOPS :%s",textbuffer);
1035 /* convert a string to lowercase. Note following special circumstances
1036 * taken from RFC 1459. Many "official" server branches still hold to this
1037 * rule so i will too;
1039 * Because of IRC's scandanavian origin, the characters {}| are
1040 * considered to be the lower case equivalents of the characters []\,
1041 * respectively. This is a critical issue when determining the
1042 * equivalence of two nicknames.
1045 void strlower(char *n)
1049 for (char* t = n; *t; t++)
1050 *t = lowermap[(unsigned)*t];
1054 /* Find a user record by nickname and return a pointer to it */
1056 userrec* Find(std::string nick)
1058 user_hash::iterator iter = clientlist.find(nick);
1060 if (iter == clientlist.end())
1061 /* Couldn't find it */
1064 return iter->second;
1067 userrec* Find(const char* nick)
1071 user_hash::iterator iter = clientlist.find(nick);
1073 if (iter == clientlist.end())
1076 return iter->second;
1079 /* find a channel record by channel name and return a pointer to it */
1081 chanrec* FindChan(const char* chan)
1085 log(DEFAULT,"*** BUG *** Findchan was given an invalid parameter");
1089 chan_hash::iterator iter = chanlist.find(chan);
1091 if (iter == chanlist.end())
1092 /* Couldn't find it */
1095 return iter->second;
1099 long GetMaxBans(char* name)
1102 for (std::map<std::string,int>::iterator n = Config->maxbans.begin(); n != Config->maxbans.end(); n++)
1105 if (match(name,x.c_str()))
1113 void purge_empty_chans(userrec* u)
1118 // firstly decrement the count on each channel
1119 for (unsigned int f = 0; f < u->chans.size(); f++)
1121 if (u->chans[f].channel)
1123 u->chans[f].channel->DelUser((char*)u);
1127 for (unsigned int i = 0; i < u->chans.size(); i++)
1129 if (u->chans[i].channel)
1131 if (!usercount(u->chans[i].channel))
1133 chan_hash::iterator i2 = chanlist.find(u->chans[i].channel->name);
1134 /* kill the record */
1135 if (i2 != chanlist.end())
1137 log(DEBUG,"del_channel: destroyed: %s",i2->second->name);
1140 FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(i2->second));
1145 u->chans[i].channel = NULL;
1150 log(DEBUG,"skipped purge for %s",u->chans[i].channel->name);
1154 log(DEBUG,"completed channel purge, killed %lu",(unsigned long)purge);
1160 char* chanmodes(chanrec *chan, bool showkey)
1162 static char scratch[MAXBUF];
1163 static char sparam[MAXBUF];
1164 char* offset = scratch;
1168 log(DEFAULT,"*** BUG *** chanmodes was given an invalid parameter");
1175 if (chan->binarymodes & CM_NOEXTERNAL)
1177 if (chan->binarymodes & CM_TOPICLOCK)
1183 if (chan->binarymodes & CM_INVITEONLY)
1185 if (chan->binarymodes & CM_MODERATED)
1187 if (chan->binarymodes & CM_SECRET)
1189 if (chan->binarymodes & CM_PRIVATE)
1193 snprintf(sparam,MAXBUF," %s",showkey ? chan->key : "<key>");
1198 sprintf(foo," %lu",(unsigned long)chan->limit);
1199 strlcat(sparam,foo,MAXBUF);
1201 for (int n = 0; n < 190; n++)
1203 if (chan->custom_modes[n])
1206 std::string extparam = chan->GetModeParameter(n+65);
1209 charlcat(sparam,' ',MAXBUF);
1210 strlcat(sparam,extparam.c_str(),MAXBUF);
1214 /* Null terminate scratch */
1216 strlcat(scratch,sparam,MAXMODES);
1221 /* compile a userlist of a channel into a string, each nick seperated by
1222 * spaces and op, voice etc status shown as @ and + */
1224 void userlist(userrec *user,chanrec *c)
1226 if ((!c) || (!user))
1228 log(DEFAULT,"*** BUG *** userlist was given an invalid parameter");
1232 size_t dlen = snprintf(list,MAXBUF,"353 %s = %s :", user->nick, c->name);
1233 size_t initial = dlen;
1235 std::map<char*,char*> *ulist= c->GetUsers();
1237 for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
1239 char* o = i->second;
1240 userrec* otheruser = (userrec*)o;
1241 if ((!has_channel(user,c)) && (strchr(otheruser->modes,'i')))
1243 /* user is +i, and source not on the channel, does not show
1244 * nick in NAMES list */
1247 dlen += strlcat(list,cmode(otheruser,c),MAXBUF);
1248 dlen += strlcat(list,otheruser->nick,MAXBUF);
1249 charlcat(list,' ',MAXBUF);
1251 if (dlen > (480-NICKMAX))
1253 /* list overflowed into
1254 * multiple numerics */
1255 WriteServ_NoFormat(user->fd,list);
1256 dlen = snprintf(list,MAXBUF,"353 %s = %s :", user->nick, c->name);
1259 /* if whats left in the list isnt empty, send it */
1260 if (dlen != initial)
1262 WriteServ_NoFormat(user->fd,list);
1266 /* return a count of the users on a specific channel accounting for
1267 * invisible users who won't increase the count. e.g. for /LIST */
1269 int usercount_i(chanrec *c)
1275 log(DEFAULT,"*** BUG *** usercount_i was given an invalid parameter");
1279 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
1281 if (has_channel(i->second,c))
1283 if (i->second->registered == 7)
1285 if ((!has_channel(i->second,c)) && (strchr(i->second->modes,'i')))
1287 /* user is +i, and source not on the channel, does not show
1288 * nick in NAMES list */
1295 log(DEBUG,"usercount_i: %s %lu",c->name,(unsigned long)count);
1300 int usercount(chanrec *c)
1302 return (c ? c->GetUserCounter() : 0);
1306 // looks up a users password for their connection class (<ALLOW>/<DENY> tags)
1308 ConnectClass GetClass(userrec *user)
1310 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
1312 if (match(user->host,i->host.c_str()))
1317 return *(Config->Classes.begin());
1320 /* sends out an error notice to all connected clients (not to be used
1323 void send_error(char *s)
1325 log(DEBUG,"send_error: %s",s);
1326 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
1328 userrec* t = (userrec*)(*i);
1329 if (t->registered == 7)
1331 WriteServ(t->fd,"NOTICE %s :%s",t->nick,s);
1335 // fix - unregistered connections receive ERROR, not NOTICE
1336 Write(t->fd,"ERROR :%s",s);
1341 void Error(int status)
1343 signal (SIGALRM, SIG_IGN);
1344 signal (SIGPIPE, SIG_IGN);
1345 signal (SIGTERM, SIG_IGN);
1346 signal (SIGABRT, SIG_IGN);
1347 signal (SIGSEGV, SIG_IGN);
1348 signal (SIGURG, SIG_IGN);
1349 signal (SIGKILL, SIG_IGN);
1350 log(DEFAULT,"*** fell down a pothole in the road to perfection ***");
1351 send_error("Error! Segmentation fault! save meeeeeeeeeeeeee *splat!*");
1355 // this function counts all users connected, wether they are registered or NOT.
1358 return clientlist.size();
1361 // this counts only registered users, so that the percentages in /MAP don't mess up when users are sitting in an unregistered state
1362 int registered_usercount(void)
1365 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
1367 if (i->second->registered == 7) c++;
1372 int usercount_invisible(void)
1375 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
1377 if ((i->second->registered == 7) && (strchr(i->second->modes,'i'))) c++;
1382 int usercount_opers(void)
1385 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
1386 if (*i->second->oper) c++;
1390 int usercount_unknown(void)
1393 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
1395 userrec* t = (userrec*)(*i);
1396 if (t->registered != 7)
1402 long chancount(void)
1404 return chanlist.size();
1410 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
1412 userrec* t = (userrec*)(*i);
1413 if (t->registered == 7) c++;
1418 void ShowMOTD(userrec *user)
1420 static char mbuf[MAXBUF];
1421 static char crud[MAXBUF];
1422 std::string WholeMOTD = "";
1423 if (!Config->MOTD.size())
1425 WriteServ(user->fd,"422 %s :Message of the day file is missing.",user->nick);
1428 snprintf(crud,MAXBUF,":%s 372 %s :- ", Config->ServerName, user->nick);
1429 snprintf(mbuf,MAXBUF,":%s 375 %s :- %s message of the day\r\n", Config->ServerName, user->nick, Config->ServerName);
1430 WholeMOTD = WholeMOTD + mbuf;
1431 for (unsigned int i = 0; i < Config->MOTD.size(); i++)
1432 WholeMOTD = WholeMOTD + std::string(crud) + Config->MOTD[i].c_str() + std::string("\r\n");
1433 snprintf(mbuf,MAXBUF,":%s 376 %s :End of message of the day.\r\n", Config->ServerName, user->nick);
1434 WholeMOTD = WholeMOTD + mbuf;
1435 // only one write operation
1436 if (Config->GetIOHook(user->port))
1440 Config->GetIOHook(user->port)->OnRawSocketWrite(user->fd,(char*)WholeMOTD.c_str(),WholeMOTD.length());
1442 catch (ModuleException& modexcept)
1444 log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
1450 user->AddWriteBuf(WholeMOTD);
1452 ServerInstance->stats->statsSent += WholeMOTD.length();
1455 void ShowRULES(userrec *user)
1457 if (!Config->RULES.size())
1459 WriteServ(user->fd,"NOTICE %s :Rules file is missing.",user->nick);
1462 WriteServ(user->fd,"NOTICE %s :%s rules",user->nick,Config->ServerName);
1463 for (unsigned int i = 0; i < Config->RULES.size(); i++)
1464 WriteServ(user->fd,"NOTICE %s :%s",user->nick,Config->RULES[i].c_str());
1465 WriteServ(user->fd,"NOTICE %s :End of %s rules.",user->nick,Config->ServerName);
1468 // this returns 1 when all modules are satisfied that the user should be allowed onto the irc server
1469 // (until this returns true, a user will block in the waiting state, waiting to connect up to the
1470 // registration timeout maximum seconds)
1471 bool AllModulesReportReady(userrec* user)
1473 if (!Config->global_implementation[I_OnCheckReady])
1475 for (int i = 0; i <= MODCOUNT; i++)
1477 if (Config->implement_lists[i][I_OnCheckReady])
1479 int res = modules[i]->OnCheckReady(user);
1487 bool DirValid(char* dirandfile)
1490 char buffer[MAXBUF], otherdir[MAXBUF];
1491 strlcpy(work,dirandfile,MAXBUF);
1492 int p = strlen(work);
1493 // we just want the dir
1503 // Get the current working directory
1504 if( getcwd( buffer, MAXBUF ) == NULL )
1507 if( getcwd( otherdir, MAXBUF ) == NULL )
1510 if (strlen(otherdir) >= strlen(work))
1512 otherdir[strlen(work)] = '\0';
1513 if (!strcmp(otherdir,work))
1522 std::string GetFullProgDir(char** argv, int argc)
1525 char buffer[MAXBUF], otherdir[MAXBUF];
1526 strlcpy(work,argv[0],MAXBUF);
1527 int p = strlen(work);
1528 // we just want the dir
1538 // Get the current working directory
1539 if( getcwd( buffer, MAXBUF ) == NULL )
1542 if( getcwd( otherdir, MAXBUF ) == NULL )
1548 int InsertMode(std::string &output, const char* mode, unsigned short section)
1550 unsigned short currsection = 1;
1551 unsigned int pos = output.find("CHANMODES=", 0) + 10; // +10 for the length of "CHANMODES="
1553 if(section > 4 || section == 0)
1555 log(DEBUG, "InsertMode: CHANMODES doesn't have a section %dh :/", section);
1559 for(; pos < output.size(); pos++)
1561 if(section == currsection)
1564 if(output[pos] == ',')
1568 output.insert(pos, mode);
1572 bool IsValidChannelName(const char *chname)
1576 /* check for no name - don't check for !*chname, as if it is empty, it won't be '#'! */
1577 if (!chname || *chname != '#')
1582 c = (char *)chname + 1;
1596 /* too long a name - note funky pointer arithmetic here. */
1597 if ((c - chname) > CHANMAX)
1605 inline int charlcat(char* x,char y,int z)
1619 bool charremove(char* mp, char remove)
1622 bool shift_down = false;
1625 if (*mptr == remove)