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_whois.c

633 lines
16 KiB
C
Raw Permalink Normal View History

2002-08-13 14:34:25 +00:00
/*
* NeoIRCd: NeoStats Group. Based on Hybird7
2002-08-13 14:34:25 +00:00
* m_whois.c: Shows who a user is.
*
* Copyright (C) 2002 by the past and present ircd coders, and others.
*
* 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
2003-03-06 14:01:51 +00:00
* $Id: m_whois.c,v 1.12 2003/03/06 14:01:47 fishwaldo Exp $
2002-08-13 14:34:25 +00:00
*/
#include "stdinc.h"
#include "tools.h"
#include "common.h"
#include "handlers.h"
#include "client.h"
#include "hash.h"
#include "channel.h"
#include "channel_mode.h"
#include "hash.h"
#include "ircd.h"
#include "numeric.h"
#include "s_conf.h"
#include "s_serv.h"
#include "s_user.h"
2002-08-13 14:34:25 +00:00
#include "send.h"
#include "list.h"
#include "irc_string.h"
#include "s_conf.h"
#include "msg.h"
#include "parse.h"
#include "modules.h"
#include "hook.h"
static int do_whois(struct Client *client_p, struct Client *source_p,
int parc, char *parv[]);
static int single_whois(struct Client *source_p, struct Client *target_p,
int wilds, int glob);
static void whois_person(struct Client *source_p,struct Client *target_p,int glob);
static int global_whois(struct Client *source_p, char *nick, int wilds, int glob);
static void m_whois(struct Client*, struct Client*, int, char**);
static void ms_whois(struct Client*, struct Client*, int, char**);
static void mo_whois(struct Client*, struct Client*, int, char**);
struct Message whois_msgtab = {
"WHOIS", 0, 0, 0, 0, MFLG_SLOW, 0L,
{m_unregistered, m_whois, ms_whois, mo_whois}
};
#ifndef STATIC_MODULES
void
_modinit(void)
{
hook_add_event("doing_whois");
mod_add_cmd(&whois_msgtab);
}
void
_moddeinit(void)
{
hook_del_event("doing_whois");
mod_del_cmd(&whois_msgtab);
}
2003-03-06 14:01:51 +00:00
const char *_version = "$Revision: 1.12 $";
2002-08-13 14:34:25 +00:00
#endif
/*
** m_whois
** parv[0] = sender prefix
** parv[1] = nickname masklist
*/
static void
m_whois(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
2002-08-13 14:34:25 +00:00
{
static time_t last_used = 0;
if (parc < 2 || BadPtr(parv[1]))
{
sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
me.name, parv[0]);
return;
}
2002-08-13 14:34:25 +00:00
if(parc > 2)
{
/* seeing as this is going across servers, we should limit it */
if((last_used + ConfigFileEntry.pace_wait_simple) > CurrentTime)
{
if(MyClient(source_p))
sendto_one(source_p,form_str(RPL_LOAD2HI),me.name,source_p->name);
return;
}
else
last_used = CurrentTime;
2002-08-13 14:34:25 +00:00
/* if we have serverhide enabled, they can either ask the clients
* server, or our server.. I dont see why they would need to ask
* anything else for info about the client.. --fl_
*/
if(ConfigServerHide.disable_remote)
2002-08-13 14:34:25 +00:00
parv[1] = parv[2];
if (hunt_server(client_p,source_p,":%s WHOIS %s :%s", 1, parc, parv) !=
HUNTED_ISME)
{
return;
2002-08-13 14:34:25 +00:00
}
parv[1] = parv[2];
}
2002-08-13 14:34:25 +00:00
do_whois(client_p,source_p,parc,parv);
}
/*
** mo_whois
** parv[0] = sender prefix
** parv[1] = nickname masklist
*/
static void
mo_whois(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
2002-08-13 14:34:25 +00:00
{
/* XXX Need BadPtr */
if (parc < 2 || BadPtr(parv[1]))
2002-08-13 14:34:25 +00:00
{
sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
me.name, parv[0]);
return;
}
if(parc > 2)
{
if (hunt_server(client_p,source_p,":%s WHOIS %s :%s", 1, parc, parv) !=
HUNTED_ISME)
{
return;
}
parv[1] = parv[2];
}
do_whois(client_p,source_p,parc,parv);
}
/* do_whois
*
* inputs - pointer to
* output -
* side effects -
*/
static int
do_whois(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
2002-08-13 14:34:25 +00:00
{
struct Client *target_p;
char *nick;
char *p = NULL;
int found=NO;
int wilds;
int glob=0;
/* This lets us make all "whois nick" queries look the same, and all
* "whois nick nick" queries look the same. We have to pass it all
* the way down to whois_person() though -- fl */
if(parc > 2)
glob = 1;
nick = parv[1];
while (*nick == ',')
nick++;
if ((p = strchr(nick,',')) != NULL)
2002-08-13 14:34:25 +00:00
*p = '\0';
if (*nick == '\0')
return(0);
2002-08-13 14:34:25 +00:00
(void)collapse(nick);
wilds = (strchr(nick, '?') || strchr(nick, '*'));
if(!wilds)
{
if((target_p = find_client(nick)) != NULL)
2002-08-13 14:34:25 +00:00
{
/* im being asked to reply to a client that isnt mine..
* I cant answer authoritively, so better make it non-detailed
*/
if(!MyClient(target_p))
glob=0;
2002-08-13 14:34:25 +00:00
if (IsServer(client_p))
client_burst_if_needed(client_p,target_p);
if(IsPerson(target_p))
{
(void)single_whois(source_p,target_p,wilds,glob);
found = YES;
}
2002-08-13 14:34:25 +00:00
}
else
2002-08-13 14:34:25 +00:00
{
if (!ServerInfo.hub && uplink && IsCapable(uplink,CAP_LL))
{
if(glob)
sendto_one(uplink,":%s WHOIS %s :%s",
source_p->name, nick, nick);
else
sendto_one(uplink,":%s WHOIS %s",
source_p->name, nick);
return (0);
}
}
}
else /* wilds is true */
{
/* disallow wild card whois on lazylink leafs for now */
if (!ServerInfo.hub && uplink && IsCapable(uplink,CAP_LL))
{
return (0);
2002-08-13 14:34:25 +00:00
}
/* Oh-oh wilds is true so have to do it the hard expensive way */
found = global_whois(source_p,nick,wilds,glob);
}
2002-08-13 14:34:25 +00:00
2003-03-06 14:01:51 +00:00
if (!found)
2002-08-13 14:34:25 +00:00
sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, parv[0], nick);
return (0);
2002-08-13 14:34:25 +00:00
}
/*
* global_whois()
*
* Inputs - source_p client to report to
* - target_p client to report on
* - wilds whether wildchar char or not
* Output - if found return 1
* Side Effects - do a single whois on given client
* writing results to source_p
*/
static int
global_whois(struct Client *source_p, char *nick, int wilds, int glob)
2002-08-13 14:34:25 +00:00
{
struct Client *target_p;
int found = NO;
for (target_p = GlobalClientList; (target_p = next_client(target_p, nick));
target_p = target_p->next)
{
if (IsServer(target_p))
continue;
/*
* I'm always last :-) and target_p->next == NULL!!
*/
if (IsMe(target_p))
break;
/*
* 'Rules' established for sending a WHOIS reply:
*
*
* - if wildcards are being used dont send a reply if
* the querier isnt any common channels and the
* client in question is invisible and wildcards are
* in use (allow exact matches only);
*
* - only send replies about common or public channels
* the target user(s) are on;
*/
2002-08-13 14:34:25 +00:00
if(!IsRegistered(target_p))
continue;
2002-08-13 14:34:25 +00:00
if(single_whois(source_p, target_p, wilds, glob))
found = (YES);
}
2002-08-13 14:34:25 +00:00
return (found);
}
/*
* single_whois()
*
* Inputs - source_p client to report to
* - target_p client to report on
* - wilds whether wildchar char or not
* Output - if found return 1
* Side Effects - do a single whois on given client
* writing results to source_p
*/
static int
single_whois(struct Client *source_p,struct Client *target_p,
int wilds, int glob)
2002-08-13 14:34:25 +00:00
{
dlink_node *ptr;
struct Channel *chptr;
char *name;
int invis;
int member;
int showperson;
if (target_p->name[0] == '\0')
name = "?";
else
name = target_p->name;
if( target_p->user == NULL )
{
sendto_one(source_p, form_str(RPL_WHOISUSER), me.name,
source_p->name, name,
2002-08-13 14:45:13 +00:00
target_p->username, target_p->vhost, target_p->info);
2002-08-13 14:34:25 +00:00
sendto_one(source_p, form_str(RPL_WHOISSERVER),
me.name, source_p->name, name, "<Unknown>",
"*Not On This Net*");
return 0;
}
invis = IsInvisible(target_p);
member = (target_p->user->channel.head) ? 1 : 0;
showperson = (wilds && !invis && !member) || !wilds;
DLINK_FOREACH(ptr, target_p->user->channel.head)
{
chptr = ptr->data;
member = IsMember(source_p, chptr);
if (invis && !member)
continue;
if (member || (!invis && PubChannel(chptr)))
2002-08-13 14:34:25 +00:00
{
showperson = 1;
break;
2002-08-13 14:34:25 +00:00
}
if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr))
{
showperson = 1;
break;
}
}
2002-08-13 14:34:25 +00:00
if(showperson)
whois_person(source_p,target_p,glob);
return (YES);
2002-08-13 14:34:25 +00:00
}
/*
* whois_person()
*
* Inputs - source_p client to report to
* - target_p client to report on
* Output - NONE
* Side Effects -
*/
static void
whois_person(struct Client *source_p,struct Client *target_p, int glob)
2002-08-13 14:34:25 +00:00
{
char buf[BUFSIZE];
char *chname;
char *server_name;
dlink_node *lp;
struct Client *a2client_p;
struct Channel *chptr;
int cur_len = 0;
int mlen;
char *t;
int tlen;
int reply_to_send = NO;
struct hook_mfunc_data hd;
char ubuf[BUFSIZE];
2002-08-13 14:34:25 +00:00
a2client_p = find_server(target_p->user->server);
sendto_one(source_p, form_str(RPL_WHOISUSER), me.name,
source_p->name, target_p->name,
2002-08-13 14:45:13 +00:00
target_p->username, target_p->vhost, target_p->info);
2002-08-13 14:34:25 +00:00
server_name = (char *)target_p->user->server;
ircsprintf(buf, form_str(RPL_WHOISCHANNELS),
me.name, source_p->name, target_p->name, "");
mlen = strlen(buf);
cur_len = mlen;
t = buf + mlen;
DLINK_FOREACH(lp, target_p->user->channel.head)
{
chptr = lp->data;
chname = chptr->chname;
2002-08-13 14:34:25 +00:00
if (ShowChannel(source_p, chptr))
{
if ((cur_len + strlen(chname) + 2) > (BUFSIZE - 4))
{
sendto_one(source_p, "%s", buf);
cur_len = mlen;
t = buf + mlen;
}
2002-08-13 14:34:25 +00:00
if (chptr->mode.mode & MODE_HIDEOPS && !is_any_op(chptr,source_p))
{
ircsprintf(t,"%s ",chname);
}
else
{
ircsprintf(t,"%s%s ", channel_chanop_or_voice(chptr,target_p), chname);
}
2002-08-13 14:34:25 +00:00
tlen = strlen(t);
t += tlen;
cur_len += tlen;
reply_to_send = YES;
2002-08-13 14:34:25 +00:00
}
}
2002-08-13 14:34:25 +00:00
if (reply_to_send)
sendto_one(source_p, "%s", buf);
if ((IsOper(source_p) || !ConfigServerHide.hide_servers) || target_p == source_p)
sendto_one(source_p, form_str(RPL_WHOISSERVER),
2002-10-15 07:30:09 +00:00
me.name, source_p->name, target_p->name, !target_p->servptr->hidden_server ? server_name : ServerInfo.network_name,
target_p->servptr->hidden_server ? ServerInfo.network_desc : a2client_p ? a2client_p->info:"*Not On This Net*");
2002-08-13 14:34:25 +00:00
else
sendto_one(source_p, form_str(RPL_WHOISSERVER),
me.name, source_p->name, target_p->name,
ServerInfo.network_name,
ServerInfo.network_desc);
if (target_p->user->away)
sendto_one(source_p, form_str(RPL_AWAY), me.name,
source_p->name, target_p->name, target_p->user->away);
if (IsOper(target_p))
{
sendto_one(source_p, form_str(RPL_WHOISOPERATOR),
me.name, source_p->name, target_p->name);
if (IsAdmin(target_p))
sendto_one(source_p, form_str(RPL_WHOISADMIN),
2002-08-13 14:34:25 +00:00
me.name, source_p->name, target_p->name);
}
2002-08-13 14:34:25 +00:00
2002-08-13 14:45:13 +00:00
if (IsServices(target_p))
sendto_one(source_p, form_str(RPL_WHOISSERVICES),
me.name, source_p->name, target_p->name);
if (IsOper(source_p) || (source_p == target_p))
2002-08-13 14:45:13 +00:00
{
send_umode(NULL, target_p, 0, ALL_UMODES, ubuf);
if (!*ubuf)
{
ubuf[0] = '+';
ubuf[1] = '\0';
}
sendto_one(source_p, form_str(RPL_WHOISMODES),
me.name, source_p->name, target_p->name, ubuf);
sendto_one(source_p, form_str(RPL_WHOISREALHOST),
me.name, source_p->name, target_p->name, target_p->host);
}
if (target_p->umodes & FLAGS_REGNICK) {
sendto_one(source_p, form_str(RPL_WHOISREGNICK),
me.name, source_p->name, target_p->name);
}
if (target_p->umodes & FLAGS_SSL) {
sendto_one(source_p, form_str(RPL_USINGSSL),
me.name, source_p->name, target_p->name);
}
2002-08-13 14:34:25 +00:00
if ( (glob == 1) || (MyConnect(target_p) && (IsOper(source_p) ||
!ConfigServerHide.hide_servers)) || (target_p == source_p) )
{
sendto_one(source_p, form_str(RPL_WHOISIDLE),
me.name, source_p->name, target_p->name,
CurrentTime - target_p->user->last,
target_p->firsttime);
}
hd.client_p = target_p;
hd.source_p = source_p;
/* although we should fill in parc and parv, we don't ..
* be careful of this when writing whois hooks
*/
2002-08-13 14:34:25 +00:00
if(MyClient(source_p))
hook_call_event("doing_whois", &hd);
return;
}
/*
** ms_whois
** parv[0] = sender prefix
** parv[1] = nickname masklist
*/
/* Be warned, this is heavily commented, as theres loads of possibilities
* that can happen, and as people might not understand the code, I
* stuck heavy comments in it.. it looks ugly.. but at least you
* know what it does.. --fl_ */
static void
ms_whois(struct Client *client_p, struct Client *source_p,
int parc, char *parv[])
2002-08-13 14:34:25 +00:00
{
/* its a misconfigured server */
/* XXX Need BadPtr */
if (parc < 2 || BadPtr(parv[1]))
2002-08-13 14:34:25 +00:00
{
sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
me.name, parv[0]);
return;
}
if(!IsClient(source_p))
return;
2002-08-13 14:34:25 +00:00
/* its a client doing a remote whois:
* :parv[0] WHOIS parv[1] :parv[2]
*
* parv[0] == sender
* parv[1] == server to reply to the request
* parv[2] == the client we are whois'ing
*/
if(parc > 2)
{
struct Client *target_p;
/* check if parv[1] is a client.. (most common) */
if((target_p = find_client(parv[1])) == NULL)
{
/* ok, parv[1] isnt a client, is it a server? */
if((target_p = find_server(parv[1])) == NULL)
{
/* its not a server either.. theyve sent a bad whois */
sendto_one(source_p, form_str(ERR_NOSUCHSERVER), me.name,
parv[0], parv[1]);
return;
}
}
/* its been found as a client.. to save extra work later, change
* target_p to be the clients uplink.. you cant check if a client
* supports being a LL :P
*/
else
target_p = target_p->servptr;
/* if parv[1] isnt my client, or me, someone else is supposed
* to be handling the request.. so send it to them
*/
if(!MyClient(target_p) && !IsMe(target_p))
{
/* we're being asked to forward a whois request to a LL to answer,
* if the target isnt on that server.. answer it for them, as the
* LL might not know that the target exists..
*/
if(MyConnect(target_p) && ServerInfo.hub && IsCapable(target_p, CAP_LL))
2002-08-13 14:34:25 +00:00
{
struct Client *whois_p;
/* try to find the client */
if ((whois_p = find_client(parv[2])) != NULL)
2002-08-13 14:34:25 +00:00
{
/* check the server being asked to perform the whois, is that
* clients uplink */
if(whois_p->servptr != target_p)
{
/* they asked the LL for info on a client it didnt know about..
* as we're answering for them, make sure its non-detailed
*/
parv[1] = parv[2];
parc = 2;
do_whois(client_p, source_p, parc, parv);
return;
}
/* the server is that clients uplink, get them to do it */
else
{
client_burst_if_needed(target_p->from, source_p);
sendto_one(target_p->from, ":%s WHOIS %s :%s", parv[0], parv[1],
parv[2]);
return;
}
}
/* the client doesnt exist.. erk! */
else
{
/* set parv[1] = parv[2], then let do_whois handle the error */
parv[1] = parv[2];
do_whois(client_p, source_p, parc, parv);
return;
}
}
/* its not a lazylink.. forward it as it is */
else
{
/* client_burst_if_needed(target_p->from, source_p);
* the target isnt a LL.. why would I need to burst? */
sendto_one(target_p->from, ":%s WHOIS %s :%s", parv[0], parv[1],
parv[2]);
return;
2002-08-13 14:34:25 +00:00
}
}
/* ok, the target is either us, or a client on our server, so perform the whois
* but first, parv[1] == server to perform the whois on, parv[2] == person
* to whois, so make parv[1] = parv[2] so do_whois is ok -- fl_
*/
parv[1] = parv[2];
do_whois(client_p,source_p,parc,parv);
return;
}
/* parc == 2, so its a lazylink client asking us about a nick, so do it */
do_whois(client_p, source_p, parc, parv);
return;
}