/* * IRC - Internet Relay Chat, modules/m_list.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_list.c,v 1.5 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 "h.h" #include "msg.h" void send_list(aClient *, LOpts *); static struct Message _msgtab[] = { {MSG_LIST, 0, MAXPARA, M_SLOW, 0L, m_unregistered, m_list, m_list, m_ignore, m_ignore} }; #ifndef STATIC_MODULES char *_version = "$Revision: 1.5 $"; void _modinit(void) { mod_add_cmd(_msgtab); } void _moddeinit(void) { mod_del_cmd(_msgtab); } #else void m_list_init(void) { mod_add_cmd(_msgtab); } #endif /* * * m_list * parv[0] = sender prefix * parv[1] = channel */ int m_list(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aChannel *chptr; time_t currenttime = time(NULL); char *name, *cp, *p = NULL; LOpts *lopt = sptr->lopts; dlink_node *lp; int usermax, usermin, error = 0, doall = 0; int x; time_t chantimemin, chantimemax; long topictimemin, topictimemax; dlink_list yeslist, nolist; static char *usage[] = { "", "If you don't include any options, the default is to send you the", "entire unfiltered list of channels. Below are the options you can", "use, and what channels LIST will return when you use them.", ">number List channels with more than people.", " people.", "C>number List channels created between now and minutes ago.", "C minutes ago.", "T>number List channels whose topics are older than minutes", " (Ie, they have not changed in the last minutes.", "T minutes.", "*mask* List channels that match *mask*", "!*mask* List channels that do not match *mask*", NULL }; /* * Some starting san checks -- No interserver lists allowed. */ if (cptr != sptr || !sptr->user) return 0; if (parc < 2 || BadPtr(parv[1])) { send_me_numeric(sptr, RPL_LISTSTART); lopt = (LOpts *) MyMalloc(sizeof(LOpts)); memset(lopt, '\0', sizeof(LOpts)); lopt->showall = 1; send_list(cptr, lopt); return 0; } if ((parc == 2) && (parv[1][0] == '?') && (parv[1][1] == '\0')) { char **ptr = usage; for (; *ptr; ptr++) send_me_numeric(sptr, RPL_COMMANDSYNTAX, *ptr); return 0; } send_me_numeric(sptr, RPL_LISTSTART); chantimemax = topictimemax = currenttime + 86400; chantimemin = topictimemin = 0; usermin = 1; usermax = -1; /* No maximum */ memset(&yeslist, 0, sizeof(yeslist)); memset(&nolist, 0, sizeof(nolist)); yeslist.head = NULL; yeslist.tail = NULL; nolist.head = NULL; nolist.tail = NULL; for (name = strtoken(&p, parv[1], ","); name && !error; name = strtoken(&p, (char *) NULL, ",")) { switch (*name) { case '<': usermax = atoi(name + 1) - 1; doall = 1; break; case '>': usermin = atoi(name + 1) + 1; doall = 1; break; case 'C': case 'c': /* Channel TS time -- creation time? */ ++name; switch (*name++) { case '<': chantimemax = currenttime - 60 * atoi(name); doall = 1; break; case '>': chantimemin = currenttime - 60 * atoi(name); doall = 1; break; default: send_me_numeric(sptr, ERR_LISTSYNTAX); error = 1; } break; case 'T': case 't': ++name; switch (*name++) { case '<': topictimemax = currenttime - 60 * atoi(name); doall = 1; break; case '>': topictimemin = currenttime - 60 * atoi(name); doall = 1; break; default: send_me_numeric(sptr, ERR_LISTSYNTAX); error = 1; } break; default: /* A channel, possibly with wildcards. Thought * for the future: Consider turning wildcard * processing on the fly. new syntax: * !channelmask will tell ircd to ignore any * channels matching that mask, and then * channelmask will tell ircd to send us a list * of channels only masking channelmask. * Note: Specifying a channel without wildcards * will return that channel even if any of * the !channelmask masks matches it. */ if (*name == '!') { doall = 1; lp = make_dlink_node(); DupString(cp, name + 1); dlinkAdd(cp, lp, &nolist); } else if (strchr(name, '*') || strchr(name, '*')) { doall = 1; lp = make_dlink_node(); DupString(cp, name); dlinkAdd(cp, lp, &yeslist); } else { /* Just a normal channel */ chptr = find_channel(name); if (chptr && ((x = ShowChannel(sptr, chptr)) || IsSeeHidden(sptr))) { char *nameptr = name; char channame[CHANNELLEN + 2]; if (!x && IsSeeHidden(sptr)) { channame[0] = '%'; strcpy(&channame[1], chptr->chname); nameptr = channame; } send_me_numeric(sptr, RPL_LIST, nameptr, chptr->users, chptr->topic); } /* 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 */ } } /* switch */ } /* while */ if (doall) { lopt = (LOpts *) MyMalloc(sizeof(LOpts)); memset(lopt, '\0', sizeof(LOpts)); lopt->usermin = usermin; lopt->usermax = usermax; lopt->topictimemax = topictimemax; lopt->topictimemin = topictimemin; lopt->chantimemax = chantimemax; lopt->chantimemin = chantimemin; if (nolist.head) dlinkMoveList(&nolist, &lopt->nolist); if (yeslist.head) dlinkMoveList(&yeslist, &lopt->yeslist); send_list(cptr, lopt); return 0; } send_me_numeric(sptr, RPL_LISTEND); return 0; }