/*
* IRC - Internet Relay Chat, modules/m_mode.c
*
* Copyright (C) 2000-2003 TR-IRCD Development
*
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Co Center
*
* 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 2, 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.
*/
/*
* $Id: m_mode.c,v 1.13 2004/02/24 15:00:27 tr-ircd Exp $
*/
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "channel.h"
#include "chanmode.h"
#include "usermode.h"
#include "msg.h"
#include "h.h"
#include "language.h"
static char modebuf[REALMODEBUFLEN], parabuf[REALMODEBUFLEN];
static char *m_token = TOK1_MODE;
static char *t_token = TOK1_TMODE;
static struct Message m_msgtab[] = {
{MSG_MODE, 0, MAXPARA, M_SLOW | M_FLOOD_END, 0L,
m_unregistered, m_mode, m_mode, m_mode, m_ignore}
};
static struct Message t_msgtab[] = {
{MSG_TMODE, 0, MAXPARA, M_SLOW, 0L,
m_unregistered, m_ignore, m_ignore, m_tmode, m_ignore}
};
#ifndef STATIC_MODULES
char *_version = "$Revision: 1.13 $";
void _modinit(void)
{
mod_add_cmd(m_msgtab);
mod_add_cmd(t_msgtab);
tok1_msgtab[(u_char) *m_token].msg = m_msgtab;
tok1_msgtab[(u_char) *t_token].msg = t_msgtab;
}
void _moddeinit(void)
{
mod_del_cmd(m_msgtab);
mod_del_cmd(t_msgtab);
tok1_msgtab[(u_char) *m_token].msg = NULL;
tok1_msgtab[(u_char) *t_token].msg = NULL;
}
#else
void m_mode_init(void)
{
mod_add_cmd(m_msgtab);
mod_add_cmd(t_msgtab);
tok1_msgtab[(u_char) *m_token].msg = m_msgtab;
tok1_msgtab[(u_char) *t_token].msg = t_msgtab;
}
#endif
int m_mode(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
int mcount = 0;
int link_mode = 0;
aChannel *chptr;
if (parc > 1) {
/* We do not need link traversal here, because users
* do not exist in the root channel, and it is already
* set to +tnL, after cleaning. -TimeMr14C
*/
chptr = find_channel(parv[1]);
if (!chptr)
return m_umode(cptr, sptr, parc, parv);
} else {
send_me_numeric(sptr, ERR_NEEDMOREPARAMS, MSG_MODE);
return 0;
}
if (!check_channelname(sptr, (unsigned char *) parv[1]))
return 0;
*modebuf = *parabuf = '\0';
if (parc < 3) {
modebuf[1] = '\0';
channel_modes(sptr, modebuf, parabuf, chptr, 1);
send_me_numeric(sptr, RPL_CHANNELMODEIS, chptr, modebuf, parabuf);
send_me_numeric(sptr, RPL_CREATIONTIME, chptr, chptr->tsval);
return 0;
}
if (IsChanLinked(chptr))
link_mode = 1;
mcount = set_mode(cptr, sptr, chptr, parc - 2, parv + 2, modebuf, parabuf);
if (strlen(modebuf) > (size_t) 1) {
switch (mcount) {
case 0:
break;
case -1:
if (MyClient(sptr))
send_me_numeric(sptr, ERR_CHANOPRIVSNEEDED, chptr);
else
ircstp->is_fake++;
break;
default:
sendto_channel_butserv(chptr, sptr, TOK1_MODE, CHFL_GETSETTER,
"%s %s", modebuf, parabuf);
sendto_service(SERVICE_SEE_MODES, 0, sptr, chptr, TOK1_MODE,
"%s %s", modebuf, parabuf);
sendto_serv_butone(cptr, sptr, TOK1_TMODE, "%H %T %s %s",
chptr, chptr, modebuf, parabuf);
}
}
if (link_mode) {
if (!IsChanLinked(chptr)) {
remove_user_from_channel(&me, chptr);
}
} else {
if (IsChanLinked(chptr)) {
link_add_server_to_channel(&me, chptr);
link_remove_users_from_channel(chptr);
link_set_modes_in_channel(chptr);
}
}
ClearOperMode(sptr);
return 0;
}
int m_tmode(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
int mcount = 0;
int link_mode = 0;
unsigned long tts = 0;
aChannel *chptr;
if (parc < 4)
return 0;
/* !ID TMODE #channel timestamp modes parameters */
if (!(chptr = find_channel(parv[1])))
return 0;
/* We do not do link traversal here. We want the remote
* to set the modes for the correct channel. -TimeMr14C */
*modebuf = *parabuf = '\0';
tts = strtoul(parv[2], NULL, 0);
if (tts > chptr->tsval) {
sendto_lev(DEBUG_LEV, "Got TMODE from %C for %H with wrong timestamp. (%lu != %T)",
cptr, chptr, tts, chptr);
return 0;
}
if (IsChanLinked(chptr))
link_mode = 1;
mcount = set_mode(cptr, sptr, chptr, parc - 3, parv + 3, modebuf, parabuf);
if (strlen(modebuf) > (size_t) 1) {
switch (mcount) {
case 0:
break;
case -1:
ircstp->is_fake++;
break;
default:
sendto_channel_butserv(chptr, sptr, TOK1_MODE, CHFL_GETSETTER,
"%s %s", modebuf, parabuf);
sendto_service(SERVICE_SEE_MODES, 0, sptr, chptr, TOK1_MODE,
"%s %s", modebuf, parabuf);
sendto_serv_butone(cptr, sptr, TOK1_TMODE, "%H %T %s %s",
chptr, chptr, modebuf, parabuf);
}
}
if (link_mode)
if (!IsChanLinked(chptr))
remove_user_from_channel(&me, chptr);
return 0;
}
static char buf[BUFSIZE];
/*
* m_umode() added 15/10/91 By Darren Reed. parv[0] - sender parv[1] -
* username to change mode for parv[2] - modes to change
*/
int m_umode(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
long flag = 0;
int i;
char **p, *m;
aClient *acptr;
int what;
long setflags;
int badflag = 0;
dlink_node *ptr;
what = CMODE_ADD;
if (parc < 2) {
send_me_numeric(sptr, ERR_NEEDMOREPARAMS, MSG_MODE);
return 0;
}
if (!(acptr = find_person(parv[1]))) {
if (MyConnect(sptr))
send_me_numeric(sptr, ERR_NOSUCHNICK, parv[1]);
return 0;
}
if ((IsServer(sptr) || (sptr != acptr) || (acptr->from != sptr->from))) {
if (!IsServer(cptr))
send_me_numeric(sptr, ERR_USERSDONTMATCH);
return 0;
}
if (parc < 3) {
m = buf;
*m++ = '+';
for (i = 64; i < 127; i++) {
if (umodetab[i].in_use) {
flag = umodetab[i].type;
if (sptr->umode & flag)
*m++ = i;
}
}
*m = '\0';
send_me_numeric(sptr, RPL_UMODEIS, buf);
return 0;
}
/*
* find flags already set for user
*/
setflags = 0;
for (i = 64; i < 127; i++) {
if (umodetab[i].in_use) {
flag = umodetab[i].type;
if (sptr->umode & flag)
setflags |= flag;
}
}
/*
* parse mode change string(s)
*/
for (p = &parv[2]; p && *p; p++) {
for (m = *p; *m; m++) {
if ((int) *m != 43 && (int) *m != 45) {
if ((int) *m < 64)
continue;
if ((int) *m > 126)
continue;
}
switch (*m) {
case '+':
what = CMODE_ADD;
break;
case '-':
what = CMODE_DEL;
break;
/*
* we may not get these, but they shouldnt be in
* default
*/
case ' ':
case '\r':
case '\n':
case '\t':
case 'h':
case 'r':
break; /* users can't set themselves +r or +h! */
case 'L':
if (!MyClient(sptr)) {
if ((parc > 4) && IsDigit(parv[3][0])) {
if (sptr->tsval == strtoul(parv[3], NULL, 0)) {
if (IsDigit(parv[4][0]))
sptr->lang = set_language(atoi(parv[4]));
}
}
}
break;
case 'o':
if (!MyClient(sptr)) {
if (what == CMODE_ADD)
SetOper(sptr);
}
if (what == CMODE_DEL)
sptr->umode &= ~UMODE_o;
break;
default:
if (umodetab[(int) *m].in_use) {
flag = umodetab[(int) *m].type;
if (what == CMODE_ADD) {
if (umodetab[(int) *m].require_flags) {
if (sptr->umode & umodetab[(int) *m].require_flags)
sptr->umode |= flag;
} else {
sptr->umode |= flag;
}
} else {
if (umodetab[(int) *m].remove_flags)
sptr->umode &= ~umodetab[(int) *m].remove_flags;
sptr->umode &= ~flag;
}
}
if (flag == 0 && MyConnect(sptr))
badflag = 1;
break;
}
}
}
if (badflag)
send_me_numeric(sptr, ERR_UMODEUNKNOWNFLAG);
if ((setflags & UMODE_o) && !IsAnOper(sptr) && MyConnect(sptr)) {
det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPERATOR);
sptr->sendqlen = get_sendq(sptr);
sptr->oflag = 0;
ptr = dlinkFind(&locoper_list, sptr);
if (ptr != NULL) {
dlinkDelete(ptr, &locoper_list);
free_dlink_node(ptr);
}
}
if ((setflags & UMODE_o) && !IsAnOper(sptr))
Count.oper--;
if (!(setflags & UMODE_o) && IsAnOper(sptr) && !MyConnect(sptr))
Count.oper++;
if (!(setflags & UMODE_i) && IsInvisible(sptr))
Count.invisi++;
if ((setflags & UMODE_i) && !IsInvisible(sptr))
Count.invisi--;
if (MyClient(sptr)) {
if (IsAdmin(sptr) && !OPIsAdmin(sptr))
sptr->umode &= ~UMODE_A;
if (IsSAdmin(sptr) && !OPIsSAdmin(sptr))
sptr->umode &= ~UMODE_a;
if (IsSeeHidden(sptr) && !OPIsSeeHidden(sptr))
sptr->umode &= ~UMODE_H;
if (IsAdmin(sptr) && !IsSAdmin(sptr))
sptr->umode &= ~UMODE_a;
}
send_umode_out(cptr, sptr, setflags);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1