📄 m_message.c
字号:
/* * Unreal Internet Relay Chat Daemon, src/modules/m_message.c * (C) 2000-2001 Carsten V. Munk and the UnrealIRCd Team * Moved to modules by Fish (Justin Hammond) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "config.h"#include "struct.h"#include "common.h"#include "sys.h"#include "numeric.h"#include "msg.h"#include "channel.h"#include <time.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef _WIN32#include <io.h>#endif#include <fcntl.h>#include "h.h"#include "proto.h"#ifdef STRIPBADWORDS#include "badwords.h"#endif#ifdef _WIN32#include "version.h"#endif#include "badwords.h"int _is_silenced(aClient *, aClient *);char *_stripbadwords_channel(char *str, int *blocked);char *_stripbadwords_message(char *str, int *blocked);char *_stripbadwords_quit(char *str, int *blocked);char *_StripColors(unsigned char *text);char *_StripControlCodes(unsigned char *text);DLLFUNC int m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int notice);DLLFUNC int m_notice(aClient *cptr, aClient *sptr, int parc, char *parv[]);DLLFUNC int m_private(aClient *cptr, aClient *sptr, int parc, char *parv[]);extern int webtv_parse(aClient *sptr, char *string);/* Place includes here */#define MSG_PRIVATE "PRIVMSG" /* PRIV */#define TOK_PRIVATE "!" /* 33 */#define MSG_NOTICE "NOTICE" /* NOTI */#define TOK_NOTICE "B" /* 66 */ModuleHeader MOD_HEADER(m_message) = { "message", /* Name of module */ "$Id: m_message.c,v 1.1.6.10 2006/12/22 21:10:33 syzop Exp $", /* Version */ "private message and notice", /* Short description of module */ "3.2-b8-1", NULL };DLLFUNC int MOD_TEST(m_message)(ModuleInfo *modinfo){ MARK_AS_OFFICIAL_MODULE(modinfo); EfunctionAddPChar(modinfo->handle, EFUNC_STRIPBADWORDS_CHANNEL, _stripbadwords_channel); EfunctionAddPChar(modinfo->handle, EFUNC_STRIPBADWORDS_MESSAGE, _stripbadwords_message); EfunctionAddPChar(modinfo->handle, EFUNC_STRIPBADWORDS_QUIT, _stripbadwords_quit); EfunctionAddPChar(modinfo->handle, EFUNC_STRIPCOLORS, _StripColors); EfunctionAddPChar(modinfo->handle, EFUNC_STRIPCONTROLCODES, _StripControlCodes); EfunctionAdd(modinfo->handle, EFUNC_IS_SILENCED, _is_silenced); return MOD_SUCCESS;}/* This is called on module init, before Server Ready */DLLFUNC int MOD_INIT(m_message)(ModuleInfo *modinfo){ /* * We call our add_Command crap here */ add_CommandX(MSG_PRIVATE, TOK_PRIVATE, m_private, 2, M_USER|M_SERVER|M_RESETIDLE|M_VIRUS); add_Command(MSG_NOTICE, TOK_NOTICE, m_notice, 2); MARK_AS_OFFICIAL_MODULE(modinfo); return MOD_SUCCESS; }/* Is first run when server is 100% ready */DLLFUNC int MOD_LOAD(m_message)(int module_load){ return MOD_SUCCESS;}/* Called when module is unloaded */DLLFUNC int MOD_UNLOAD(m_message)(int module_unload){ if (del_Command(MSG_PRIVATE, TOK_PRIVATE, m_private) < 0) { sendto_realops("Failed to delete command privmsg when unloading %s", MOD_HEADER(m_message).name); } if (del_Command(MSG_NOTICE, TOK_NOTICE, m_notice) < 0) { sendto_realops("Failed to delete command notice when unloading %s", MOD_HEADER(m_message).name); } return MOD_SUCCESS;}static int check_dcc(aClient *sptr, char *target, aClient *targetcli, char *text);static int check_dcc_soft(aClient *from, aClient *to, char *text);#define CANPRIVMSG_CONTINUE 100#define CANPRIVMSG_SEND 101/** Check if PRIVMSG's are permitted from a person to another person. * cptr: .. * sptr: .. * acptr: target client * notice: 1 if notice, 0 if privmsg * text: Pointer to a pointer to a text [in, out] * cmd: Pointer to a pointer which contains the command to use [in, out] * * RETURN VALUES: * CANPRIVMSG_CONTINUE: issue a 'continue' in target nickname list (aka: skip further processing this target) * CANPRIVMSG_SEND: send the message (use text/newcmd!) * Other: return with this value (can be anything like 0, -1, FLUSH_BUFFER, etc) */static int can_privmsg(aClient *cptr, aClient *sptr, aClient *acptr, int notice, char **text, char **cmd){char *ctcp;int ret; if (IsVirus(sptr)) { sendnotice(sptr, "You are only allowed to talk in '%s'", SPAMFILTER_VIRUSCHAN); return CANPRIVMSG_CONTINUE; } /* Umode +R (idea from Bahamut) */ if (IsRegNickMsg(acptr) && !IsRegNick(sptr) && !IsULine(sptr) && !IsOper(sptr) && !IsServer(sptr)) { sendto_one(sptr, err_str(ERR_NONONREG), me.name, sptr->name, acptr->name); return 0; } if (IsNoCTCP(acptr) && !IsOper(sptr) && **text == 1 && acptr != sptr) { ctcp = *text + 1; /* &*text[1]; */ if (myncmp(ctcp, "ACTION ", 7) && myncmp(ctcp, "DCC ", 4)) { sendto_one(sptr, err_str(ERR_NOCTCP), me.name, sptr->name, acptr->name); return 0; } } if (MyClient(sptr) && !strncasecmp(*text, "\001DCC", 4)) { ret = check_dcc(sptr, acptr->name, acptr, *text); if (ret < 0) return ret; if (ret == 0) return CANPRIVMSG_CONTINUE; } if (MyClient(acptr) && !strncasecmp(*text, "\001DCC", 4) && !check_dcc_soft(sptr, acptr, *text)) return CANPRIVMSG_CONTINUE; if (MyClient(sptr) && check_for_target_limit(sptr, acptr, acptr->name)) return CANPRIVMSG_CONTINUE; if (!is_silenced(sptr, acptr)) {#ifdef STRIPBADWORDS int blocked = 0;#endif Hook *tmphook; if (notice && IsWebTV(acptr) && **text != '\1') *cmd = MSG_PRIVATE; if (!notice && MyConnect(sptr) && acptr->user && acptr->user->away) sendto_one(sptr, rpl_str(RPL_AWAY), me.name, sptr->name, acptr->name, acptr->user->away);#ifdef STRIPBADWORDS if (MyClient(sptr) && !IsULine(acptr) && IsFilteringWords(acptr)) { *text = stripbadwords_message(*text, &blocked); if (blocked) { if (!notice && MyClient(sptr)) sendto_one(sptr, rpl_str(ERR_NOSWEAR), me.name, sptr->name, acptr->name); return CANPRIVMSG_CONTINUE; } }#endif if (MyClient(sptr)) { ret = dospamfilter(sptr, *text, (notice ? SPAMF_USERNOTICE : SPAMF_USERMSG), acptr->name, 0, NULL); if (ret < 0) return ret; } for (tmphook = Hooks[HOOKTYPE_USERMSG]; tmphook; tmphook = tmphook->next) { *text = (*(tmphook->func.pcharfunc))(cptr, sptr, acptr, *text, notice); if (!*text) break; } if (!*text) return CANPRIVMSG_CONTINUE; return CANPRIVMSG_SEND; } else { /* Silenced */ RunHook4(HOOKTYPE_SILENCED, cptr, sptr, acptr, notice); } return CANPRIVMSG_CONTINUE;}/*** m_message (used in m_private() and m_notice())** the general function to deliver MSG's between users/channels**** parv[0] = sender prefix** parv[1] = receiver list** parv[2] = message text**** massive cleanup** rev argv 6/91***/static int recursive_webtv = 0;DLLFUNC int m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int notice){ aClient *acptr, *srvptr; char *s; aChannel *chptr; char *nick, *server, *p, *cmd, *ctcp, *p2, *pc, *text, *newcmd; int cansend = 0; int prefix = 0; char pfixchan[CHANNELLEN + 4]; int ret; /* * Reasons why someone can't send to a channel */ static char *err_cantsend[] = { "You need voice (+v)", "No external channel messages", "Color is not permitted in this channel", "You are banned", "CTCPs are not permitted in this channel", "You must have a registered nick (+r) to talk on this channel", "Swearing is not permitted in this channel", "NOTICEs are not permitted in this channel", NULL }; if (IsHandshake(sptr)) return 0; cmd = notice ? MSG_NOTICE : MSG_PRIVATE; if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], cmd); return -1; } if (parc < 3 || *parv[2] == '\0') { sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]); return -1; } if (MyConnect(sptr)) parv[1] = (char *)canonize(parv[1]); for (p = NULL, nick = strtoken(&p, parv[1], ","); nick; nick = strtoken(&p, NULL, ",")) { if (IsVirus(sptr) && (!strcasecmp(nick, "ircd") || !strcasecmp(nick, "irc"))) { sendnotice(sptr, "IRC command(s) unavailable because you are suspected to have a virus"); continue; } /* ** nickname addressed? */ if (!strcasecmp(nick, "ircd") && MyClient(sptr)) { ret = 0; if (!recursive_webtv) { recursive_webtv = 1; ret = parse(sptr, parv[2], (parv[2] + strlen(parv[2]))); recursive_webtv = 0; } return ret; } if (!strcasecmp(nick, "irc") && MyClient(sptr)) { if (!recursive_webtv) { recursive_webtv = 1; ret = webtv_parse(sptr, parv[2]); if (ret == -99) { ret = parse(sptr, parv[2], (parv[2] + strlen(parv[2]))); } recursive_webtv = 0; return ret; } } if (*nick != '#' && (acptr = find_person(nick, NULL))) { text = parv[2]; newcmd = cmd; ret = can_privmsg(cptr, sptr, acptr, notice, &text, &newcmd); if (ret == CANPRIVMSG_SEND) { sendto_message_one(acptr, sptr, parv[0], newcmd, nick, text); continue; } else if (ret == CANPRIVMSG_CONTINUE) continue; else return ret; } p2 = (char *)strchr(nick, '#'); prefix = 0; if (p2 && (chptr = find_channel(p2, NullChn))) { if (p2 != nick) { for (pc = nick; pc != p2; pc++) {#ifdef PREFIX_AQ #define PREFIX_REST (PREFIX_ADMIN|PREFIX_OWNER)#else #define PREFIX_REST (0)#endif switch (*pc) { case '+': prefix |= PREFIX_VOICE | PREFIX_HALFOP | PREFIX_OP | PREFIX_REST; break; case '%': prefix |= PREFIX_HALFOP | PREFIX_OP | PREFIX_REST; break; case '@': prefix |= PREFIX_OP | PREFIX_REST; break;#ifdef PREFIX_AQ case '&': prefix |= PREFIX_ADMIN | PREFIX_OWNER; break; case '~': prefix |= PREFIX_OWNER; break;#else case '&': prefix |= PREFIX_OP | PREFIX_REST; break; case '~': prefix |= PREFIX_OP | PREFIX_REST; break;#endif default: break; /* ignore it :P */ } } if (prefix) { if (MyClient(sptr) && !op_can_override(sptr)) { Membership *lp = find_membership_link(sptr->user->channel, chptr); /* Check if user is allowed to send. RULES: * Need at least voice (+) in order to send to +,% or @ * Need at least ops (@) in order to send to & or ~ */ if (!lp || !(lp->flags & (CHFL_VOICE|CHFL_HALFOP|CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT))) { sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, sptr->name, chptr->chname); return 0; } if (!(prefix & PREFIX_OP) && ((prefix & PREFIX_OWNER) || (prefix & PREFIX_ADMIN)) && !(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT))) { sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, sptr->name, chptr->chname); return 0; } } /* Now find out the lowest prefix and use that.. (so @&~#chan becomes @#chan) */ if (prefix & PREFIX_VOICE) pfixchan[0] = '+'; else if (prefix & PREFIX_HALFOP) pfixchan[0] = '%'; else if (prefix & PREFIX_OP) pfixchan[0] = '@';#ifdef PREFIX_AQ else if (prefix & PREFIX_ADMIN) pfixchan[0] = '&'; else if (prefix & PREFIX_OWNER) pfixchan[0] = '~';#endif else abort(); strlcpy(pfixchan+1, p2, sizeof(pfixchan)-1); nick = pfixchan; } else { strlcpy(pfixchan, p2, sizeof(pfixchan)); nick = pfixchan; } } if (MyClient(sptr) && (*parv[2] == 1)) { ret = check_dcc(sptr, chptr->chname, NULL, parv[2]); if (ret < 0) return ret; if (ret == 0) continue; } if (IsVirus(sptr) && strcasecmp(chptr->chname, SPAMFILTER_VIRUSCHAN)) { sendnotice(sptr, "You are only allowed to talk in '%s'", SPAMFILTER_VIRUSCHAN); continue; } cansend = !IsULine(sptr) ? can_send(sptr, chptr, parv[2], notice) : 0; if (!cansend) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -