⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_mode.c

📁 Unreal irc 服务器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *   IRC - Internet Relay Chat, src/modules/m_mode.c *   (C) 2005 The UnrealIRCd Team * *   See file AUTHORS in IRC package for additional names of *   the programmers. * *   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 "proto.h"#include "channel.h"#include "macros.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"#ifdef STRIPBADWORDS#include "badwords.h"#endif#ifdef _WIN32#include "version.h"#endif/* Forward declarations */DLLFUNC CMD_FUNC(m_mode);DLLFUNC void _do_mode(aChannel *chptr, aClient *cptr, aClient *sptr, int parc, char *parv[], time_t sendts, int samode);DLLFUNC void _set_mode(aChannel *chptr, aClient *cptr, int parc, char *parv[], u_int *pcount,    char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], int bounce);DLLFUNC CMD_FUNC(_m_umode);/* local: */static void bounce_mode(aChannel *, aClient *, int, char **);int do_mode_char(aChannel *chptr, long modetype, char modechar, char *param,    u_int what, aClient *cptr,     u_int *pcount, char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], char bounce, long my_access);int do_extmode_char(aChannel *chptr, int modeindex, char *param, u_int what,                    aClient *cptr, u_int *pcount, char pvar[MAXMODEPARAMS][MODEBUFLEN + 3],                    char bounce);#ifdef EXTCMODEvoid make_mode_str(aChannel *chptr, long oldm, Cmode_t oldem, long oldl, int pcount,    char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], char *mode_buf, char *para_buf, char bounce);#elsevoid make_mode_str(aChannel *chptr, long oldm, long oldl, int pcount,    char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], char *mode_buf, char *para_buf, char bounce);#endifstatic void mode_cutoff(char *s);static int samode_in_progress = 0;#define MSG_MODE 	"MODE"	#define TOK_MODE 	"G"	ModuleHeader MOD_HEADER(m_mode)  = {	"m_mode",	"$Id: m_mode.c,v 1.1.4.5 2006/12/22 21:10:33 syzop Exp $",	"command /mode", 	"3.2-b8-1",	NULL     };DLLFUNC int MOD_TEST(m_mode)(ModuleInfo *modinfo){	MARK_AS_OFFICIAL_MODULE(modinfo);	EfunctionAddVoid(modinfo->handle, EFUNC_DO_MODE, _do_mode);	EfunctionAddVoid(modinfo->handle, EFUNC_SET_MODE, _set_mode);	EfunctionAdd(modinfo->handle, EFUNC_M_UMODE, _m_umode);	return MOD_SUCCESS;}DLLFUNC int MOD_INIT(m_mode)(ModuleInfo *modinfo){	CommandAdd(modinfo->handle, MSG_MODE, TOK_MODE, m_mode, MAXPARA, M_USER|M_SERVER);	MARK_AS_OFFICIAL_MODULE(modinfo);	return MOD_SUCCESS;}DLLFUNC int MOD_LOAD(m_mode)(int module_load){	return MOD_SUCCESS;}DLLFUNC int MOD_UNLOAD(m_mode)(int module_unload){	return MOD_SUCCESS;}/* * m_mode -- written by binary (garryb@binary.islesfan.net) *	Completely rewrote it.  The old mode command was 820 lines of ICKY * coding, which is a complete waste, because I wrote it in 570 lines of * *decent* coding.  This is also easier to read, change, and fine-tune.  Plus, * everything isn't scattered; everything's grouped where it should be. * * parv[0] - sender * parv[1] - channel */CMD_FUNC(m_mode){	long unsigned sendts = 0;	Ban *ban;	aChannel *chptr;	/* Now, try to find the channel in question */	if (parc > 1)	{		if (*parv[1] == '#')		{			chptr = find_channel(parv[1], NullChn);			if (chptr == NullChn)			{				return m_umode(cptr, sptr, parc, parv);			}		}		else			return m_umode(cptr, sptr, parc, parv);	}	else	{		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),		    me.name, parv[0], "MODE");		return 0;	}	if (MyConnect(sptr))		clean_channelname(parv[1]);	if (check_channelmask(sptr, cptr, parv[1]))		return 0;	if (parc < 3)	{		*modebuf = *parabuf = '\0';				modebuf[1] = '\0';		channel_modes(sptr, modebuf, parabuf, chptr);		sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],		    chptr->chname, modebuf, parabuf);		sendto_one(sptr, rpl_str(RPL_CREATIONTIME), me.name, parv[0],		    chptr->chname, chptr->creationtime);		return 0;	}	if (IsPerson(sptr) && parc < 4 && ((*parv[2] == 'b'	    && parv[2][1] == '\0') || (parv[2][1] == 'b' && parv[2][2] == '\0'	    && (*parv[2] == '+' || *parv[2] == '-'))))	{		if (!IsMember(sptr, chptr) && !IsAnOper(sptr))			return 0;		/* send ban list */		for (ban = chptr->banlist; ban; ban = ban->next)			sendto_one(sptr, rpl_str(RPL_BANLIST), me.name,			    sptr->name, chptr->chname, ban->banstr,			    ban->who, ban->when);		sendto_one(cptr,		    rpl_str(RPL_ENDOFBANLIST), me.name, sptr->name,		    chptr->chname);		return 0;	}	if (IsPerson(sptr) && parc < 4 && ((*parv[2] == 'e'	    && parv[2][1] == '\0') || (parv[2][1] == 'e' && parv[2][2] == '\0'	    && (*parv[2] == '+' || *parv[2] == '-'))))	{		if (!IsMember(sptr, chptr) && !IsAnOper(sptr))			return 0;		/* send exban list */		for (ban = chptr->exlist; ban; ban = ban->next)			sendto_one(sptr, rpl_str(RPL_EXLIST), me.name,			    sptr->name, chptr->chname, ban->banstr,			    ban->who, ban->when);		sendto_one(cptr,		    rpl_str(RPL_ENDOFEXLIST), me.name, sptr->name,		    chptr->chname);		return 0;	}	if (IsPerson(sptr) && parc < 4 && ((*parv[2] == 'q'	    && parv[2][1] == '\0') || (parv[2][1] == 'q' && parv[2][2] == '\0'	    && (*parv[2] == '+' || *parv[2] == '-'))))	{		if (!IsMember(sptr, chptr) && !IsAnOper(sptr))			return 0;		{			Member *member;			/* send chanowner list */			/* [Whole story about bad loops removed, sorry ;)]			 * Now rewritten so it works (was: bad logic) -- Syzop			 */			for (member = chptr->members; member; member = member->next)			{				if (is_chanowner(member->cptr, chptr))					sendto_one(sptr, rpl_str(RPL_QLIST),					    me.name, sptr->name, chptr->chname,					    member->cptr->name);			}			sendto_one(cptr,			    rpl_str(RPL_ENDOFQLIST), me.name, sptr->name,			    chptr->chname);			return 0;		}	}	if (IsPerson(sptr) && parc < 4 && ((*parv[2] == 'a'	    && parv[2][1] == '\0') || (parv[2][1] == 'a' && parv[2][2] == '\0'	    && (*parv[2] == '+' || *parv[2] == '-'))))	{		if (!IsMember(sptr, chptr) && !IsAnOper(sptr))			return 0;		{			Member *member;			/* send chanowner list */			/* [Whole story about bad loops removed, sorry ;)]			 * Now rewritten so it works (was: bad logic) -- Syzop			 */			for (member = chptr->members; member; member = member->next)			{				if (is_chanprot(member->cptr, chptr))					sendto_one(sptr, rpl_str(RPL_ALIST),					    me.name, sptr->name, chptr->chname,					    member->cptr->name);			}			sendto_one(cptr,			    rpl_str(RPL_ENDOFALIST), me.name, sptr->name,			    chptr->chname);			return 0;		}	}	if (IsPerson(sptr) && parc < 4 && ((*parv[2] == 'I'	    && parv[2][1] == '\0') || (parv[2][1] == 'I' && parv[2][2] == '\0'	    && (*parv[2] == '+' || *parv[2] == '-'))))	{		if (!IsMember(sptr, chptr) && !IsAnOper(sptr))			return 0;		for (ban = chptr->invexlist; ban; ban = ban->next)			sendto_one(sptr, rpl_str(RPL_INVEXLIST), me.name,			    sptr->name, chptr->chname, ban->banstr,			    ban->who, ban->when);		sendto_one(sptr, rpl_str(RPL_ENDOFINVEXLIST), me.name,		    sptr->name, chptr->chname);		return 0;	}	opermode = 0;#ifndef NO_OPEROVERRIDE        if (IsPerson(sptr) && !IsULine(sptr) && !is_chan_op(sptr, chptr)            && !is_half_op(sptr, chptr) && (MyClient(sptr) ? (IsOper(sptr) &&	    OPCanOverride(sptr)) : IsOper(sptr)))        {                sendts = 0;                opermode = 1;                goto aftercheck;        }        if (IsPerson(sptr) && !IsULine(sptr) && !is_chan_op(sptr, chptr)            && is_half_op(sptr, chptr) && (MyClient(sptr) ? (IsOper(sptr) &&	    OPCanOverride(sptr)) : IsOper(sptr)))        {                opermode = 2;                goto aftercheck;        }#endif	if (IsPerson(sptr) && !IsULine(sptr) && !is_chan_op(sptr, chptr)	    && !is_half_op(sptr, chptr)	    && (cptr == sptr || !IsSAdmin(sptr) || !IsOper(sptr)))	{		if (cptr == sptr)		{			sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),			    me.name, parv[0], chptr->chname);			return 0;		}		sendto_one(cptr, ":%s MODE %s -oh %s %s 0",		    me.name, chptr->chname, parv[0], parv[0]);		/* Tell the other server that the user is		 * de-opped.  Fix op desyncs. */		bounce_mode(chptr, cptr, parc - 2, parv + 2);		return 0;	}	if (IsServer(sptr) && (sendts = TS2ts(parv[parc - 1]))	    && !IsULine(sptr) && chptr->creationtime	    && sendts > chptr->creationtime)	{		if (!(*parv[2] == '&'))	/* & denotes a bounce */		{			/* !!! */			sendto_snomask(SNO_EYES,			    "*** TS bounce for %s - %lu(ours) %lu(theirs)",			    chptr->chname, chptr->creationtime, sendts);			bounce_mode(chptr, cptr, parc - 2, parv + 2);		}		return 0;	}	if (IsServer(sptr) && !sendts && *parv[parc - 1] != '0')		sendts = -1;	if (IsServer(sptr) && sendts != -1)		parc--;		/* server supplied a time stamp, remove it now */      aftercheck:/*	if (IsPerson(sptr) && IsOper(sptr)) {		if (!is_chan_op(sptr, chptr)) {			if (MyClient(sptr) && !IsULine(cptr) && mode_buf[1])				sendto_snomask(SNO_EYES, "*** OperMode [IRCop: %s] - [Channel: %s] - [Mode: %s %s]",        	 		   sptr->name, chptr->chname, mode_buf, parabuf);			sendts = 0;		}	}	*/	/* This is to prevent excess +<whatever> modes. -- Syzop */	if (MyClient(sptr) && parv[2])		mode_cutoff(parv[2]);	/* Filter out the unprivileged FIRST. *	 * Now, we can actually do the mode.  */	(void)do_mode(chptr, cptr, sptr, parc - 2, parv + 2, sendts, 0);	opermode = 0; /* Important since sometimes forgotten. -- Syzop */	return 0;}/** Cut off mode string (eg: +abcdfjkdsgfgs) at MAXMODEPARAMS modes. * @param s The mode string (modes only, no parameters) * @notes Should only used on local clients * @author Syzop */static void mode_cutoff(char *s){unsigned short modesleft = MAXMODEPARAMS * 2; /* be generous... */	for (; *s && modesleft; s++)		if ((*s != '-') && (*s != '+'))			modesleft--;	*s = '\0';}/* bounce_mode -- written by binary *	User or server is NOT authorized to change the mode.  This takes care * of making the bounce string and bounce it.  Because of the 1 for the bounce * param (last param) of the calls to set_mode and make_mode_str, it will not * set the mode, but create the bounce string. */static void bounce_mode(aChannel *chptr, aClient *cptr, int parc, char *parv[]){	char pvar[MAXMODEPARAMS][MODEBUFLEN + 3];	int  pcount;	set_mode(chptr, cptr, parc, parv, &pcount, pvar, 1);	if (chptr->creationtime)		sendto_one(cptr, ":%s MODE %s &%s %s %lu", me.name,		    chptr->chname, modebuf, parabuf, chptr->creationtime);	else		sendto_one(cptr, ":%s MODE %s &%s %s", me.name, chptr->chname,		    modebuf, parabuf);	/* the '&' denotes a bounce so servers won't bounce a bounce */}/* do_mode -- written by binary *	User or server is authorized to do the mode.  This takes care of * setting the mode and relaying it to other users and servers. */DLLFUNC void _do_mode(aChannel *chptr, aClient *cptr, aClient *sptr, int parc, char *parv[], time_t sendts, int samode){	char pvar[MAXMODEPARAMS][MODEBUFLEN + 3];	int  pcount;	char tschange = 0, isbounce = 0;	/* fwd'ing bounce */	if (**parv == '&')		isbounce = 1;	/* Please keep the next 3 lines next to each other */	samode_in_progress = samode;	set_mode(chptr, sptr, parc, parv, &pcount, pvar, 0);	samode_in_progress = 0; 	if (IsServer(sptr))	{		if (sendts > 0)		{			if (!chptr->creationtime			    || sendts < chptr->creationtime)			{				tschange = 1;/*				if (chptr->creationtime != 0)					sendto_snomask(SNO_EYES, "*** TS fix for %s - %lu(ours) %lu(theirs)",					chptr->chname, chptr->creationtime, sendts);								*/				chptr->creationtime = sendts;#if 0				if (sendts < 750000)					sendto_realops(						"Warning! Possible desynch: MODE for channel %s ('%s %s') has fishy timestamp (%ld) (from %s/%s)"						chptr->chname, modebuf, parabuf, sendts, cptr->name, sptr->name);#endif				/* new chan or our timestamp is wrong */				/* now works for double-bounce prevention */			}			if (sendts > chptr->creationtime && chptr->creationtime)			{				/* theirs is wrong but we let it pass anyway */				sendts = chptr->creationtime;				sendto_one(cptr, ":%s MODE %s + %lu", me.name,				    chptr->chname, chptr->creationtime);			}		}		if (sendts == -1 && chptr->creationtime)			sendts = chptr->creationtime;	}	if (*modebuf == '\0' || (*(modebuf + 1) == '\0' && (*modebuf == '+'	    || *modebuf == '-')))	{		if (tschange || isbounce) {	/* relay bounce time changes */			if (chptr->creationtime)				sendto_serv_butone_token(cptr, me.name,				    MSG_MODE, TOK_MODE, "%s %s+ %lu",				    chptr->chname, isbounce ? "&" : "",				    chptr->creationtime);			else				sendto_serv_butone_token(cptr, me.name,				    MSG_MODE, TOK_MODE, "%s %s+ ",				    chptr->chname, isbounce ? "&" : "");		return;		/* nothing to send */		}	}	/* opermode for twimodesystem --sts */#ifndef NO_OPEROVERRIDE	if (opermode == 1)	{		if (modebuf[1])			sendto_snomask(SNO_EYES,			    "*** OperOverride -- %s (%s@%s) MODE %s %s %s",			    sptr->name, sptr->user->username, sptr->user->realhost,			    chptr->chname, modebuf, parabuf);			/* Logging Implementation added by XeRXeS */			ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) MODE %s %s %s",				sptr->name, sptr->user->username, sptr->user->realhost,				chptr->chname, modebuf, parabuf);		sendts = 0;	}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -