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

📄 m_sjoin.c

📁 Unreal irc 服务器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   IRC - Internet Relay Chat, src/modules/m_sjoin.c *   (C) 2004 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 <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"#endifDLLFUNC int m_sjoin(aClient *cptr, aClient *sptr, int parc, char *parv[]);#define MSG_SJOIN 	"SJOIN"	#define TOK_SJOIN 	"~"	ModuleHeader MOD_HEADER(m_sjoin)  = {	"m_sjoin",	"$Id: m_sjoin.c,v 1.1.6.8 2006/12/22 21:10:33 syzop Exp $",	"command /sjoin", 	"3.2-b8-1",	NULL     };DLLFUNC int MOD_INIT(m_sjoin)(ModuleInfo *modinfo){	add_Command(MSG_SJOIN, TOK_SJOIN, m_sjoin, MAXPARA);	MARK_AS_OFFICIAL_MODULE(modinfo);	return MOD_SUCCESS;}DLLFUNC int MOD_LOAD(m_sjoin)(int module_load){	return MOD_SUCCESS;}DLLFUNC int MOD_UNLOAD(m_sjoin)(int module_unload){	if (del_Command(MSG_SJOIN, TOK_SJOIN, m_sjoin) < 0)	{		sendto_realops("Failed to delete commands when unloading %s",			MOD_HEADER(m_sjoin).name);	}	return MOD_SUCCESS;}typedef struct xParv aParv;struct xParv {	int  parc;	char *parv[256];};aParv pparv;aParv *mp2parv(char *xmbuf, char *parmbuf){	int  c;	char *p, *s;	pparv.parv[0] = xmbuf;	c = 1;		for (s = (char *)strtoken(&p, parmbuf, " "); s;		s = (char *)strtoken(&p, NULL, " "))	{		pparv.parv[c] = s;		c++; /* in my dreams */	}	pparv.parv[c] = NULL;	pparv.parc = c;	return (&pparv);}/* Checks if 2 ChanFloodProt modes (chmode +f) are different. * This is a bit more complicated than 1 simple memcmp(a,b,..) because * counters are also stored in this struct so we have to do * it manually :( -- Syzop. */static int compare_floodprot_modes(ChanFloodProt *a, ChanFloodProt *b){	if (memcmp(a->l, b->l, sizeof(a->l)) ||	    memcmp(a->a, b->a, sizeof(a->a)) ||	    memcmp(a->r, b->r, sizeof(a->r)))		return 1;	else		return 0;}/*   **      m_sjoin     **   **   SJOIN will synch channels and channelmodes using the new STS1 protocol   **      that is based on the EFnet TS3 protocol.   **                           -GZ (gz@starchat.net)   **            **  Modified for UnrealIRCd by Stskeeps   **  Recoded by Stskeeps   **      parv[0] = sender prefix   **      parv[1]	aChannel *chptr;	aClient *cptr;	int  parc;	u_int *pcount;	char bounce;	char *parv[], pvar[MAXMODEPARAMS][MODEBUFLEN + 3]; = channel timestamp   **      parv[2] = channel name   ** 	     **      if (parc == 3)    **		parv[3] = nick names + modes - all in one parameter   **	   if (parc == 4)   **		parv[3] = channel modes   **		parv[4] = nick names + modes - all in one parameter   **	   if (parc > 4)   **		parv[3] = channel modes   **		parv[4 to parc - 2] = mode parameters   **		parv[parc - 1] = nick names + modes *//* Some ugly macros, but useful */#define Addit(mode,param) if ((strlen(parabuf) + strlen(param) + 11 < MODEBUFLEN) && (b <= MAXMODEPARAMS)) { \	if (*parabuf) \		strcat(parabuf, " ");\	strcat(parabuf, param);\	modebuf[b++] = mode;\	modebuf[b] = 0;\}\else {\	sendto_serv_butone_sjoin(cptr, ":%s MODE %s %s %s %lu", sptr->name, chptr->chname,\		modebuf, parabuf, chptr->creationtime); \	sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s", sptr->name, chptr->chname,\		modebuf, parabuf);\	strcpy(parabuf,param);\	/* modebuf[0] should stay what it was ('+' or '-') */ \	modebuf[1] = mode;\	modebuf[2] = '\0';\	b = 2;\}#define Addsingle(x) do { modebuf[b] = x; b++; modebuf[b] = '\0'; } while(0)#define CheckStatus(x,y) do { if (modeflags & (y)) { Addit((x), nick); } } while(0)#define AddBan(x) do { strlcat(banbuf, x, sizeof banbuf); strlcat(banbuf, " ", sizeof banbuf); } while(0)#define AddEx(x) do { strlcat(exbuf, x, sizeof exbuf); strlcat(exbuf, " ", sizeof exbuf); } while(0)#define AddInvex(x) do { strlcat(invexbuf, x, sizeof invexbuf); strlcat(invexbuf, " ", sizeof invexbuf); } while(0)CMD_FUNC(m_sjoin){	unsigned short nopara;	unsigned short nomode;	unsigned short removeours;	unsigned short removetheirs;	unsigned short merge;	/* same timestamp */	char pvar[MAXMODEPARAMS][MODEBUFLEN + 3];	char paraback[1024];#ifndef NEWCHFLOODPROT	char modeback[1024];#endif	char banbuf[1024];	char exbuf[1024];	char invexbuf[1024];	char cbuf[1024];	char buf[1024];	char nick[1024];	char *s = NULL;	aClient *acptr;	aChannel *chptr;	Member *lp;	Membership *lp2;	aParv *ap;	int pcount, i, f;	time_t ts, oldts;	unsigned short b=0,c;	Mode oldmode;	char *t, *bp, *tp, *p = NULL;	 char *s0 = NULL;	long modeflags;	Ban *ban=NULL;	char queue_s=0, queue_c=0; /* oh this is soooooo ugly :p */		if (IsClient(sptr) || parc < 3 || !IsServer(sptr))		return 0;	if (!IsChannelName(parv[2]))		return 0;	merge = nopara = nomode = removeours = removetheirs = 0;	if (SupportSJOIN(cptr) && !SupportSJ3(cptr) &&	    !strncmp(parv[4], "<none>", 6))		nopara = 1;	if (SupportSJOIN2(cptr) && !SupportSJ3(cptr) &&	    !strncmp(parv[4], "<->", 6))		nopara = 1;	if (SupportSJ3(cptr) && (parc < 6))		nopara = 1;	if (SupportSJ3(cptr))	{		if (parc < 5)			nomode = 1;	}	else	{		if (parv[3][1] == '\0')			nomode = 1;	}	chptr = get_channel(cptr, parv[2], CREATE);	if (*parv[1] != '!')		ts = (time_t)atol(parv[1]);	else		ts = (time_t)base64dec(parv[1] + 1);	if (chptr->creationtime > ts)	{		removeours = 1;		oldts = chptr->creationtime;		chptr->creationtime = ts;	}	else if ((chptr->creationtime < ts) && (chptr->creationtime != 0))		removetheirs = 1;	else if (chptr->creationtime == ts)		merge = 1;	if (chptr->creationtime == 0)	{		oldts = -1;		chptr->creationtime = ts;	}	else		oldts = chptr->creationtime;	if (ts < 750000)		if (ts != 0)			sendto_ops			    ("Warning! Possible desynch: SJOIN for channel %s has a fishy timestamp (%ld) [%s/%s]",			    chptr->chname, ts, sptr->name, cptr->name);	parabuf[0] = '\0';	modebuf[0] = '+';	modebuf[1] = '\0';	banbuf[0] = '\0';	exbuf[0] = '\0';	invexbuf[0] = '\0';	channel_modes(cptr, modebuf, parabuf, chptr);	if (removeours)	{		modebuf[0] = '-';		/* remove our modes if any */		if (modebuf[1] != '\0')		{			ap = mp2parv(modebuf, parabuf);			set_mode(chptr, cptr, ap->parc, ap->parv, &pcount,			    pvar, 0);			sendto_serv_butone_sjoin(cptr,			    ":%s MODE %s %s %s %lu",			    sptr->name, chptr->chname, modebuf, parabuf,			    chptr->creationtime);			sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s",			    sptr->name, chptr->chname, modebuf, parabuf);		}		/* remove bans */		/* reset the buffers */		modebuf[0] = '-';		modebuf[1] = '\0';		parabuf[0] = '\0';		b = 1;		while(chptr->banlist)		{			ban = chptr->banlist;			Addit('b', ban->banstr);			chptr->banlist = ban->next;			MyFree(ban->banstr);			MyFree(ban->who);			free_ban(ban);		}		while(chptr->exlist)		{			ban = chptr->exlist;			Addit('e', ban->banstr);			chptr->exlist = ban->next;			MyFree(ban->banstr);			MyFree(ban->who);			free_ban(ban);		}		while(chptr->invexlist)		{			ban = chptr->invexlist;			Addit('I', ban->banstr);			chptr->invexlist = ban->next;			MyFree(ban->banstr);			MyFree(ban->who);			free_ban(ban);		}		for (lp = chptr->members; lp; lp = lp->next)		{			lp2 = find_membership_link(lp->cptr->user->channel, chptr);			if (!lp2)			{				sendto_realops("Oops! chptr->members && !find_membership_link");				continue;			}			if (lp->flags & MODE_CHANOWNER)			{				lp->flags &= ~MODE_CHANOWNER;				Addit('q', lp->cptr->name);			}			if (lp->flags & MODE_CHANPROT)			{				lp->flags &= ~MODE_CHANPROT;				Addit('a', lp->cptr->name);			}			if (lp->flags & MODE_CHANOP)			{				lp->flags &= ~MODE_CHANOP;				Addit('o', lp->cptr->name);			}			if (lp->flags & MODE_HALFOP)			{				lp->flags &= ~MODE_HALFOP;				Addit('h', lp->cptr->name);			}			if (lp->flags & MODE_VOICE)			{				lp->flags &= ~MODE_VOICE;				Addit('v', lp->cptr->name);			}			/* Those should always match anyways  */			lp2->flags = lp->flags;		}		if (b > 1)		{			modebuf[b] = '\0';			sendto_serv_butone_sjoin(cptr,			    ":%s MODE %s %s %s %lu",			    sptr->name, chptr->chname,			    modebuf, parabuf, chptr->creationtime);			sendto_channel_butserv(chptr,			    sptr, ":%s MODE %s %s %s",			    sptr->name, chptr->chname, modebuf, parabuf);		}	}	/* Mode setting done :), now for our beloved clients */	parabuf[0] = 0;	modebuf[0] = '+';	modebuf[1] = '\0';	t = parv[parc - 1];	f = 1;	b = 1;	c = 0;	bp = buf;	strlcpy(cbuf, parv[parc-1], sizeof cbuf);	for (s = s0 = strtoken(&p, cbuf, " "); s; s = s0 = strtoken(&p, (char *)NULL, " "))	{			c = f = 0;		modeflags = 0;		i = 0;		tp = s;		while (		    (*tp == '@') || (*tp == '+') || (*tp == '%')		    || (*tp == '*') || (*tp == '~') || (*tp == '&')		    || (*tp == '"') || (*tp == '\''))		{			switch (*(tp++))			{			  case '@':				  modeflags |= CHFL_CHANOP;				  break;			  case '%':				  modeflags |= CHFL_HALFOP;				  break;			  case '+':				  modeflags |= CHFL_VOICE;				  break;			  case '*':				  modeflags |= CHFL_CHANOWNER;				  break;			  case '~':				  modeflags |= CHFL_CHANPROT;				  break;			  case '&':				  modeflags |= CHFL_BAN;								  goto getnick;				  break;			  case '"':				  modeflags |= CHFL_EXCEPT;				  goto getnick;				  break;			  case '\'':				  modeflags |= CHFL_INVEX;				  goto getnick;				  break;			}		}	     getnick:		i = 0;		while ((*tp != ' ') && (*tp != '\0'))			nick[i++] = *(tp++);	/* get nick */		nick[i] = '\0';		if (nick[0] == ' ')			continue;		if (nick[0] == '\0')			continue;		Debug((DEBUG_DEBUG, "Got nick: %s", nick));		if (!(modeflags & CHFL_BAN) && !(modeflags & CHFL_EXCEPT) && !(modeflags & CHFL_INVEX))		{			if (!(acptr = find_person(nick, NULL)))			{				sendto_snomask				    (SNO_JUNK, "Missing user %s in SJOIN for %s from %s (%s)",				    nick, chptr->chname, sptr->name,				    backupbuf);				continue;			}			if (acptr->from != sptr->from)			{				if (IsMember(acptr, chptr))				{					/* Nick collision, don't kick or it desynchs -Griever*/					continue;				}							sendto_one(sptr,				    ":%s KICK %s %s :Fake direction",				    me.name, chptr->chname,				    acptr->name);				sendto_realops				    ("Fake direction from user %s in SJOIN from %s(%s) at %s",				    nick, sptr->srvptr->name,				    sptr->name, chptr->chname);				continue;			}			if (removetheirs)			{				modeflags = 0;			}			/* [old: temporarely added for tracing user-twice-in-channel bugs -- Syzop, 2003-01-24.]			 * 2003-05-29: now traced this bug down: it's possible to get 2 joins if persons			 * at 2 different servers kick a target on a 3rd server. This will require >3 servers			 * most of the time but is also possible with only 3 if there's asynchronic lag.			 * The general rule here (and at other places as well! see kick etc) is we ignore it			 * locally (dont send a join to the chan) but propagate it to the other servers.			 * I'm not sure if the propagation is needed however -- Syzop.			 */			if (IsMember(acptr, chptr)) {#if 0				int i;

⌨️ 快捷键说明

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