ircu2/ircd/m_watch.c

224 lines
5.4 KiB
C

/*
* IRC - Internet Relay Chat, ircd/m_watch.c
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Computing Center
* Copyright (C) 2002-2007 IRC-Dev Development Team <devel@irc-dev.net>
* Copyright (C) 2002 Toni Garcia (zoltan) <zoltan@irc-dev.net>
*
* 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 3, 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$
*/
#include "config.h"
#include "client.h"
#include "hash.h"
#include "ircd.h"
#include "ircd_features.h"
#include "ircd_log.h"
#include "ircd_reply.h"
#include "ircd_string.h"
#include "list.h"
#include "numeric.h"
#include "s_user.h"
#include "send.h"
#include "watch.h"
/* #include <assert.h> -- Now using assert in ircd_log.h */
#include <stdlib.h>
#include <string.h>
/*
* m_watch - generic message handler
*
* parv[0] = sender prefix
* parv[1] = parametres
*
* The parv[1] can be separated parameters with "," or " " or both.
* If a parameter begins by '+', adds a nick.
* And if a parameter begins by '-' deletes a nick.
* If to a 'C' or 'c' is sent, deletes all the watch list.
* A 'S' or 's' gives the notify status.
* The parameter 'l' list nicks on-line and 'L' list nicks on-line and off-line.
*
* By default, the parameter is a 'l'.
*
* 2002/05/20 zoltan <zoltan@irc-dev.net>
*/
int m_watch(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
char *s, *p = 0;
int i = 0;
if (parc < 2)
{
/* Default parameter 'l' */
parc = 2;
parv[1] = "l";
}
/*
* The parameters can be separated for " " or "," or both.
*/
for (i = 0; i < parc; i++) {
for (s = ircd_strtok(&p, parv[i], ", "); s; s = ircd_strtok(&p, NULL, ", "))
{
/*
* Prefix: "+" (add) "-" (delete)
*/
if (*s == '+' || *s == '-')
{
char *nick, *p2;
char c = *s;
*s++ = '\0';
/* If nick!user@host is received we truncated it */
if (!(nick = ircd_strtok(&p2, s, "!")))
nick = s;
/* Do not admit servers, neither @, nor jockers */
if (strchr(nick, '*') || strchr(nick, '.') || strchr(nick, '@'))
continue;
if (strlen(nick) > NICKLEN)
nick[NICKLEN] = '\0';
if (!*nick)
continue;
if (c == '+') /* Add nick */
{
if (cli_user(sptr)->watches >= feature_int(FEAT_MAXWATCHS))
{
send_reply(sptr, ERR_TOOMANYWATCH, nick, feature_int(FEAT_MAXWATCHS));
continue;
}
add_nick_watch(sptr, nick);
show_status_watch(sptr, nick, RPL_NOWON, RPL_NOWOFF);
}
else if (c == '-') /* Deletes nick */
{
del_nick_watch(sptr, nick);
show_status_watch(sptr, nick, RPL_WATCHOFF, RPL_WATCHOFF);
}
continue;
}
/*
* Parameter C/c
*
* Deletes all the WATCH list.
*/
if (*s == 'C' || *s == 'c')
{
del_list_watch(sptr);
continue;
}
/*
* Parametr S/s
*
* Status the WATCH List.
*/
if (*s == 'S' || *s == 's')
{
struct Watch *wptr;
struct SLink *lp;
char line[BUFSIZE * 2];
int count = 0;
wptr = FindWatch(cli_name(sptr));
if (wptr)
for (lp = wt_watch(wptr), count = 1; (lp = lp->next); count++);
send_reply(sptr, RPL_WATCHSTAT, cli_user(sptr)->watches, count);
lp = cli_user(sptr)->watch;
if (lp)
{
*line = '\0';
strcpy(line, lp->value.wptr->wt_nick);
count = strlen(parv[0]) + strlen(cli_name(&me)) + 10 + strlen(line);
while ((lp = lp->next))
{
if ((count + strlen(lp->value.wptr->wt_nick) + 1) > 512)
{
send_reply(sptr, RPL_WATCHLIST, line);
*line = '\0';
count = strlen(cli_name(sptr)) + strlen(cli_name(&me)) + 10;
}
strcat(line, " ");
strcat(line, lp->value.wptr->wt_nick);
count += (strlen(lp->value.wptr->wt_nick) + 1);
}
send_reply(sptr, RPL_WATCHLIST, line);
}
send_reply(sptr, RPL_ENDOFWATCHLIST, *s);
continue;
}
/*
* Parameter L/l
*
* List users online and if we also especified "L" offline.
*/
if (*s == 'L' || *s == 'l')
{
struct Client *acptr;
struct SLink *lp = cli_user(sptr)->watch;
while (lp)
{
if ((acptr = FindUser(lp->value.wptr->wt_nick)))
{
send_reply(sptr, RPL_NOWON, cli_name(acptr),
cli_user(acptr)->username,
!IsAnOper(sptr) ?
cli_user(acptr)->host : cli_user(acptr)->realhost,
cli_lastnick(acptr));
}
/*
* If it specifies "L" to also send off-line.
*/
else if (*s == 'L')
{
send_reply(sptr, RPL_NOWOFF, lp->value.wptr->wt_nick,
"*", "*", lp->value.wptr->wt_lasttime);
}
lp = lp->next;
}
send_reply(sptr, RPL_ENDOFWATCHLIST, *s);
continue;
}
/* Unknown or not supported parameter.
* Ignored it :)
*/
}
}
return 0;
}