This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats-NeoIRCd/modules/m_svscmds.c

528 lines
15 KiB
C
Raw Normal View History

/************************************************************************
2002-09-13 06:56:46 +00:00
* IRC - Internet Relay Chat, m_svscmds.c
* Copyright (C) 2002 NeoIRCd Development Team
*
* 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.
*
2003-03-06 14:01:51 +00:00
* $Id: m_svscmds.c,v 1.10 2003/03/06 14:01:46 fishwaldo Exp $
*/
/* List of ircd includes from ../include/ */
#include "stdinc.h"
#include "handlers.h"
#include "client.h"
2002-09-17 11:03:21 +00:00
#include "channel.h"
#include "channel_mode.h"
#include "common.h" /* FALSE bleah */
#include "ircd.h"
#include "irc_string.h"
#include "numeric.h"
#include "fdlist.h"
#include "s_bsd.h"
#include "s_conf.h"
#include "s_log.h"
#include "s_serv.h"
#include "s_user.h"
#include "send.h"
#include "msg.h"
#include "parse.h"
#include "modules.h"
#include "hash.h"
#include "whowas.h"
/* Declare the void's initially up here, as modules dont have an
* include file, we will normally have client_p, source_p, parc
* and parv[] where:
*
* client_p == client issuing command
* source_p == where the command came from
* parc == the number of parameters
* parv == an array of the parameters
*/
static void ms_svshost(struct Client *client_p, struct Client *source_p,
int parc, char *parv[]);
static void ms_svsnick(struct Client *client_p, struct Client *source_p,
int parc, char *parv[]);
static void ms_svsid(struct Client *client_p, struct Client *source_p,
int parc, char *parv[]);
2002-09-17 11:03:21 +00:00
static void ms_svsjoin(struct Client *client_p, struct Client *source_p,
int parc, char *parv[]);
static void ms_svspart(struct Client *client_p, struct Client *source_p,
int parc, char *parv[]);
static void ms_svsmode(struct Client *client_p, struct Client *source_p,
int parc, char *parv[]);
2002-09-17 11:03:21 +00:00
static int clean_nick_name(char *);
/* Show the commands this module can handle in a msgtab
* and give the msgtab a name, here its test_msgtab
*/
struct Message svshost_msgtab = {
"SVSHOST", 0, 0, 3, 3, MFLG_SLOW, 0,
{m_ignore, m_ignore, ms_svshost, m_ignore}
};
struct Message svsnick_msgtab = {
"SVSNICK", 0, 0, 3, 3, MFLG_SLOW, 0,
{m_ignore, m_ignore, ms_svsnick, m_ignore}
};
struct Message svsid_msgtab = {
"SVSID", 0, 0, 3, 3, MFLG_SLOW, 0,
{m_ignore, m_ignore, ms_svsid, m_ignore}
};
2002-09-17 11:03:21 +00:00
struct Message svsjoin_msgtab = {
"SVSJOIN", 0, 0, 3, 0, MFLG_SLOW, 0,
{m_ignore, m_ignore, ms_svsjoin, m_ignore}
};
struct Message svspart_msgtab = {
"SVSPART", 0, 0, 3, 0, MFLG_SLOW, 0,
{m_ignore, m_ignore, ms_svspart, m_ignore}
};
struct Message svsmode_msgtab = {
"SVSMODE", 0, 0, 3, 0, MFLG_SLOW, 0,
{m_ignore, m_ignore, ms_svsmode, m_ignore}
};
2002-09-17 11:03:21 +00:00
/* Thats the msgtab finished */
#ifndef STATIC_MODULES
/* Here we tell it what to do when the module is loaded */
void
_modinit(void)
{
/* This will add the commands in test_msgtab (which is above) */
mod_add_cmd(&svshost_msgtab);
mod_add_cmd(&svsnick_msgtab);
mod_add_cmd(&svsid_msgtab);
2002-09-17 11:03:21 +00:00
mod_add_cmd(&svsjoin_msgtab);
mod_add_cmd(&svspart_msgtab);
mod_add_cmd(&svsmode_msgtab);
}
/* here we tell it what to do when the module is unloaded */
void
_moddeinit(void)
{
/* This will remove the commands in test_msgtab (which is above) */
mod_del_cmd(&svshost_msgtab);
mod_del_cmd(&svsnick_msgtab);
mod_del_cmd(&svsid_msgtab);
2002-09-17 11:03:21 +00:00
mod_del_cmd(&svsjoin_msgtab);
mod_del_cmd(&svspart_msgtab);
mod_del_cmd(&svsmode_msgtab);
}
/* When we last modified the file (shown in /modlist), this is usually:
*/
2003-03-06 14:01:51 +00:00
const char *_version = "$Revision: 1.10 $";
#endif
/*
* ms_svshost
* Changes the Targets Virtual Hostname, and also sets +x if its not set already on the target
* parv[0] = sender prefix
* parv[1] = target
* parv[2] = new hostname
*/
static void ms_svshost(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
struct Client *target_p;
target_p = find_person(parv[1]);
/* first find the target that we want to change */
if (target_p != NULL) {
if (IsServer(source_p) && IsUlined(source_p)) {
SetHidden(target_p);
strncpy(target_p->vhost, parv[2], HOSTLEN);
/* send it to the rest of the net */
sendto_server(client_p, target_p, NULL, 0, 0, LL_ICLIENT, ":%s SVSHOST %s :%s", source_p->name, target_p->name, target_p->vhost);
return;
} else {
2002-09-13 16:30:05 +00:00
sendto_realops_flags(FLAGS_ALL|FLAGS_REMOTE, L_ALL, "Non U-Lined Server %s is attempting to use svshost on %s", source_p->name, target_p->name);
return;
}
} else {
ilog(L_WARN, "svshost: Couldn't find target %s", parv[1]);
/* we couldn't find the target. Just exit */
return;
}
}
/*
* ms_svsnick
* Changes the targets nickname
* parv[0] = sender prefix
* parv[1] = target
* parv[2] = new nickname
* parv[3] = ts
*
*/
static void ms_svsnick(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
struct Client *target_p;
target_p = find_person(parv[1]);
if (target_p == NULL) {
ilog(L_WARN, "SVSNICK from %s was invalid. Can't find the client", parv[1]);
return;
}
if (!IsClient(target_p))
return;
if (!IsUlined(source_p)) {
2002-09-13 16:30:05 +00:00
sendto_realops_flags(FLAGS_ALL|FLAGS_REMOTE, L_ALL, "Non U-Lined Server %s is attempting to use svsnick on %s", source_p->name, target_p->name);
return;
}
/* first find the target that we want to change */
if (MyClient(target_p)) {
if (!clean_nick_name(parv[2]) || !strcmp(target_p->name, parv[2])) {
ilog(L_WARN, "svsnick: invalid nickname");
return;
}
target_p->tsinfo = parv[4] ? atol(parv[3]) : CurrentTime;
2003-03-06 14:01:51 +00:00
sendto_common_channels_local(target_p, 1, ":%s!%s@%s NICK :%s", target_p->name, target_p->username, target_p->vhost, parv[2]);
/* send it to the other servers */
if (target_p->user) {
add_history(target_p, 1);
sendto_server(NULL, target_p, NULL, 0, 0, LL_ICLIENT, ":%s NICK %s :%lu", target_p->name, parv[2], target_p->tsinfo);
}
if (target_p->name[0])
del_from_client_hash_table(target_p->name, target_p);
strcpy(target_p->name, parv[2]);
add_to_client_hash_table(target_p->name, target_p);
/* del all the accept entries for this nick */
del_all_accepts(target_p);
} else {
/* just relay the svsnick to a server that has this client */
sendto_one(target_p, ":%s SVSNICK %s %s :%lu", source_p->name, target_p->name, parv[2], atol(parv[3]));
}
return;
}
/* clean_nick_name()
*
* input - nickname
* output - none
* side effects - walks through the nickname, returning 0 if erroneous
*/
static int clean_nick_name(char *nick)
{
assert(nick);
if(nick == NULL)
return 0;
/* nicks cant start with a digit or - */
if (*nick == '-' || IsDigit(*nick))
return 0;
for(; *nick; nick++)
{
if(!IsNickChar(*nick))
return 0;
}
return 1;
}
/*
* ms_svsid
* Sets/Changes the Services ID for a particular Nickname
* parv[0] = sender prefix
* parv[1] = target
* parv[2] = newsvsid
*
*/
static void ms_svsid(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
struct Client *target_p;
target_p = find_person(parv[1]);
if (target_p == NULL) {
ilog(L_WARN, "SVSNICK from %s was invalid. Can't find the client", parv[1]);
return;
}
if (!IsClient(target_p))
return;
if (!IsUlined(source_p)) {
2002-09-13 16:30:05 +00:00
sendto_realops_flags(FLAGS_ALL|FLAGS_REMOTE, L_ALL, "Non U-Lined Server %s is attempting to use svsid on %s", source_p->name, target_p->name);
return;
}
/* set the new ID */
target_p->svsid = atol(parv[2]);
/* and now send it to the rest of the network */
sendto_server(client_p, target_p, NULL, 0, 0, LL_ICLIENT, ":%s SVSID %s %lu", source_p->name, target_p->name, target_p->svsid);
return;
}
2002-09-17 11:03:21 +00:00
/*
* m_svsjoin
* parv[0] = sender prefix
* parv[1] = user to force
* parv[2] = channel to force them into
*/
static void ms_svsjoin(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
struct Client *target_p;
struct Channel *chptr;
int type;
char mode;
char sjmode;
char *newch;
/* if its from a server, and its not ulined, ignore it */
if (!IsUlined(source_p) && IsServer(source_p))
return;
if((hunt_server(client_p, source_p, ":%s SVSJOIN %s %s", 1, parc, parv)) != HUNTED_ISME)
2002-09-17 11:03:21 +00:00
return;
/* if target_p is not existant, print message
* to source_p and bail - scuzzy
*/
if ((target_p = find_client(parv[1])) == NULL)
{
if (IsClient(source_p)) sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name,
source_p->name, parv[1]);
return;
}
if(!IsClient(target_p))
return;
/* select our modes from parv[2] if they exist... (chanop)*/
if(*parv[2] == '!')
2002-09-17 11:03:21 +00:00
{
type = CHFL_ADMIN;
mode = 'a';
sjmode = '!';
2002-09-17 11:03:21 +00:00
}
if(*parv[2] == '@')
{
type = CHFL_CHANOP;
mode = 'o';
sjmode = '@';
}
else if(*parv[2] == '%')
{
type = CHFL_HALFOP;
mode = 'h';
sjmode = '%';
}
else if(*parv[2] == '+')
{
type = CHFL_VOICE;
mode = 'v';
sjmode = '+';
}
else
{
type = CHFL_PEON;
mode = sjmode = '\0';
}
if(mode != '\0')
parv[2]++;
if((chptr = hash_find_channel(parv[2])) != NULL)
{
if(IsMember(target_p, chptr))
{
/* debugging is fun... */
if (IsClient(source_p)) sendto_one(source_p, ":%s NOTICE %s :*** Notice -- %s is already in %s", me.name,
source_p->name, target_p->name, chptr->chname);
return;
}
add_user_to_channel(chptr, target_p, type);
if (chptr->chname[0] != '&')
sendto_server(NULL, target_p, chptr, NOCAPS, NOCAPS, LL_ICLIENT,
2002-09-17 11:03:21 +00:00
":%s SJOIN %lu %s + :%c%s",
me.name, (unsigned long) chptr->channelts,
chptr->chname, type ? sjmode : ' ', target_p->name);
sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
target_p->name, target_p->username,
target_p->host, chptr->chname);
if(type)
sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +%c %s",
me.name, chptr->chname, mode, target_p->name);
if(chptr->topic != NULL)
{
sendto_one(target_p, form_str(RPL_TOPIC), me.name,
target_p->name, chptr->chname, chptr->topic);
sendto_one(target_p, form_str(RPL_TOPICWHOTIME),
me.name, source_p->name, chptr->chname,
chptr->topic_info, chptr->topic_time);
}
channel_member_names(target_p, chptr, chptr->chname, 1);
}
else
{
newch = parv[2];
if (!check_channel_name(newch))
{
if (IsClient(source_p)) sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
source_p->name, (unsigned char*)newch);
return;
}
/* channel name must begin with & or # */
if (!IsChannelName(newch))
{
if (IsClient(source_p)) sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
source_p->name, (unsigned char*)newch);
return;
}
/* it would be interesting here to allow an oper
* to force target_p into a channel that doesn't exist
* even more so, into a local channel when we disable
* local channels... but...
* I don't want to break anything - scuzzy
*/
if (ConfigServerHide.disable_local_channels &&
(*newch == '&'))
{
if (IsClient(source_p)) sendto_one(source_p, ":%s NOTICE %s :No such channel (%s)", me.name,
source_p->name, newch);
return;
}
/* newch can't be longer than CHANNELLEN */
if (strlen(newch) > CHANNELLEN)
{
if (IsClient(source_p)) sendto_one(source_p, ":%s NOTICE %s :Channel name is too long", me.name,
source_p->name);
return;
}
chptr = get_or_create_channel(target_p, newch, NULL);
add_user_to_channel(chptr, target_p, CHFL_CHANOP);
/* send out a join, make target_p join chptr */
if (chptr->chname[0] != '&')
sendto_server(NULL, target_p, chptr, NOCAPS, NOCAPS, LL_ICLIENT,
":%s SJOIN %lu %s +nt :!%s", me.name,
2002-09-17 11:03:21 +00:00
(unsigned long) chptr->channelts, chptr->chname,
target_p->name);
sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
target_p->name, target_p->username,
target_p->host, chptr->chname);
chptr->mode.mode |= MODE_TOPICLIMIT;
chptr->mode.mode |= MODE_NOPRIVMSGS;
sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +nt", me.name,
chptr->chname);
target_p->localClient->last_join_time = CurrentTime;
channel_member_names(target_p, chptr, chptr->chname, 1);
}
}
static void ms_svspart(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
struct Client *target_p;
struct Channel *chptr;
/* if its from a server, and its not ulined, ignore it */
if (!IsUlined(source_p) && IsServer(source_p))
return;
if((hunt_server(client_p, source_p, ":%s SVSPART %s %s", 1, parc, parv)) != HUNTED_ISME)
2002-09-17 11:03:21 +00:00
return;
/* if target_p == NULL then let the oper know */
if ((target_p = find_client(parv[1])) == NULL)
{
if (IsClient(source_p)) sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name,
source_p->name, parv[1]);
return;
}
if(!IsClient(target_p))
return;
if((chptr = hash_find_channel(parv[2])) == NULL)
{
if (IsClient(source_p)) sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
me.name, parv[0], parv[1]);
return;
}
if (!IsMember(target_p, chptr))
{
if (IsClient(source_p)) sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
me.name, parv[0], parv[2], parv[1]);
return;
}
if (chptr->chname[0] != '&')
sendto_server(target_p, target_p, chptr, NOCAPS, NOCAPS, LL_ICLIENT,
":%s PART %s :%s",
target_p->name, chptr->chname,
target_p->name);
sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s",
target_p->name, target_p->username,
target_p->host,chptr->chname,
target_p->name);
remove_user_from_channel(chptr, target_p);
}
static void ms_svsmode(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
{
if (!IsUlined(source_p))
return;
user_mode(client_p, source_p, parc, parv);
}