/* * 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; }