diff options
Diffstat (limited to 'modules/m_watch.c')
-rw-r--r-- | modules/m_watch.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/modules/m_watch.c b/modules/m_watch.c new file mode 100644 index 0000000..8e952f1 --- /dev/null +++ b/modules/m_watch.c @@ -0,0 +1,269 @@ +/* + * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd). + * m_watch.c: Maintains notify list + * + * Copyright (C) 1997 Jukka Santala (Donwulff) + * Copyright (C) 2005 by the Hybrid 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 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 + * + * $Id$ + */ + +#include "stdinc.h" +#include "client.h" +#include "irc_string.h" +#include "sprintf_irc.h" +#include "ircd.h" +#include "numeric.h" +#include "conf.h" +#include "send.h" +#include "parse.h" +#include "modules.h" +#include "s_user.h" +#include "watch.h" + + +/* + * RPL_NOWON - Online at the moment (Succesfully added to WATCH-list) + * RPL_NOWOFF - Offline at the moment (Succesfully added to WATCH-list) + * RPL_WATCHOFF - Succesfully removed from WATCH-list. + * ERR_TOOMANYWATCH - Take a guess :> Too many WATCH entries. + */ +static void +show_watch(struct Client *client_p, const char *name, + unsigned int rpl1, unsigned int rpl2) +{ + const struct Client *target_p = NULL; + + if ((target_p = find_person(client_p, name))) + sendto_one(client_p, form_str(rpl1), me.name, client_p->name, + target_p->name, target_p->username, + target_p->host, target_p->tsinfo); + else + sendto_one(client_p, form_str(rpl2), me.name, client_p->name, + name, "*", "*", 0); +} + +/* + * m_watch() + * + * parv[0] = sender prefix + * parv[1] = watch options + */ +static void +m_watch(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) +{ + dlink_node *ptr = NULL; + char *s = NULL; + char *p = NULL; + char *user; + char def[2] = "l"; + unsigned int list_requested = 0; + + /* + * Default to 'l' - list who's currently online + */ + if (parc < 2) + parv[1] = def; + + for (s = strtoken(&p, parv[1], ", "); s; + s = strtoken(&p, NULL, ", ")) + { + if ((user = strchr(s, '!'))) + *user++ = '\0'; /* Not used */ + + /* + * Prefix of "+", they want to add a name to their WATCH + * list. + */ + if (*s == '+') + { + if (*(s + 1) != '\0') + { + if (dlink_list_length(&source_p->localClient->watches) >= + ConfigFileEntry.max_watch) + { + sendto_one(source_p, form_str(ERR_TOOMANYWATCH), me.name, + source_p->name, s + 1, ConfigFileEntry.max_watch); + continue; + } + + watch_add_to_hash_table(s + 1, source_p); + } + + show_watch(source_p, s + 1, RPL_NOWON, RPL_NOWOFF); + continue; + } + + /* + * Prefix of "-", coward wants to remove somebody from their + * WATCH list. So do it. :-) + */ + if (*s == '-') + { + watch_del_from_hash_table(s + 1, source_p); + show_watch(source_p, s + 1, RPL_WATCHOFF, RPL_WATCHOFF); + continue; + } + + /* + * Fancy "C" or "c", they want to nuke their WATCH list and start + * over, so be it. + */ + if (*s == 'C' || *s == 'c') + { + watch_del_watch_list(source_p); + continue; + } + + /* + * Now comes the fun stuff, "S" or "s" returns a status report of + * their WATCH list. I imagine this could be CPU intensive if + * it's done alot, perhaps an auto-lag on this? + */ + if (*s == 'S' || *s == 's') + { + char buf[IRCD_BUFSIZE] = { '\0' }; + const struct Watch *anptr = NULL; + unsigned int count = 0; + + if (list_requested & 0x1) + continue; + + list_requested |= 0x1; + + /* + * Send a list of how many users they have on their WATCH list + * and how many WATCH lists they are on. + */ + if ((anptr = watch_find_hash(source_p->name))) + count = dlink_list_length(&anptr->watched_by); + + sendto_one(source_p, form_str(RPL_WATCHSTAT), + me.name, source_p->name, + dlink_list_length(&source_p->localClient->watches), count); + + /* + * Send a list of everybody in their WATCH list. Be careful + * not to buffer overflow. + */ + if ((ptr = source_p->localClient->watches.head) == NULL) + { + sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST), + me.name, source_p->name, *s); + continue; + } + + anptr = ptr->data; + strlcpy(buf, anptr->nick, sizeof(buf)); + + count = strlen(source_p->name) + strlen(me.name) + 10 + + strlen(buf); + + while ((ptr = ptr->next)) + { + anptr = ptr->data; + + if (count + strlen(anptr->nick) + 1 > IRCD_BUFSIZE - 2) + { + sendto_one(source_p, form_str(RPL_WATCHLIST), + me.name, source_p->name, buf); + buf[0] = '\0'; + count = strlen(source_p->name) + strlen(me.name) + 10; + } + + strcat(buf, " "); + strcat(buf, anptr->nick); + count += (strlen(anptr->nick) + 1); + } + + sendto_one(source_p, form_str(RPL_WATCHLIST), + me.name, source_p->name, buf); + sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST), + me.name, source_p->name, *s); + continue; + } + + /* + * Well that was fun, NOT. Now they want a list of everybody in + * their WATCH list AND if they are online or offline? Sheesh, + * greedy aren't we? + */ + if (*s == 'L' || *s == 'l') + { + const struct Client *target_p = NULL; + + if (list_requested & 0x2) + continue; + + list_requested |= 0x2; + + DLINK_FOREACH(ptr, source_p->localClient->watches.head) + { + const struct Watch *anptr = ptr->data; + + if ((target_p = find_person(source_p, anptr->nick))) + sendto_one(source_p, form_str(RPL_NOWON), me.name, source_p->name, + target_p->name, target_p->username, + target_p->host, target_p->tsinfo); + /* + * But actually, only show them offline if it's a capital + * 'L' (full list wanted). + */ + else if (*s == 'L') + sendto_one(source_p, form_str(RPL_NOWOFF), me.name, + source_p->name, anptr->nick, + "*", "*", anptr->lasttime); + } + + sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST), + me.name, source_p->name, *s); + continue; + } + + /* Hmm.. unknown prefix character.. Ignore it. :-) */ + } +} + +static struct Message watch_msgtab = { + "WATCH", 0, 0, 0, 1, MFLG_SLOW, 0, + { m_unregistered, m_watch, m_ignore, m_ignore, m_watch, m_ignore } +}; + +static void +module_init(void) +{ + mod_add_cmd(&watch_msgtab); + add_isupport("WATCH", NULL, ConfigFileEntry.max_watch); +} + +static void +module_exit(void) +{ + mod_del_cmd(&watch_msgtab); + delete_isupport("WATCH"); +} + +struct module module_entry = { + .node = { NULL, NULL, NULL }, + .name = NULL, + .version = "$Revision$", + .handle = NULL, + .modinit = module_init, + .modexit = module_exit, + .flags = 0 +}; |