From 096570b9f88a77c5fd2f652e644b609525fc96e6 Mon Sep 17 00:00:00 2001 From: Keith Buck Date: Wed, 5 Jan 2011 21:15:36 -0800 Subject: [PATCH] Add topic TS and channel TS constraints for /LIST. --- help/opers/list | 6 +++ include/client.h | 5 +- modules/m_list.c | 122 ++++++++++++++++++++++++++++++++++------------- src/supported.c | 2 +- 4 files changed, 96 insertions(+), 39 deletions(-) diff --git a/help/opers/list b/help/opers/list index 0cc3ae78..4fe895e0 100644 --- a/help/opers/list +++ b/help/opers/list @@ -12,5 +12,11 @@ the statistics for the given channel. Modifiers are also supported, seperated by a comma: n - List channels with more than n users + Cn - List channels older than n minutes + Tn - List channels whose topics were last changed + more than n minutes ago eg LIST <100,>20 diff --git a/include/client.h b/include/client.h index 0885b08f..2c3597f7 100644 --- a/include/client.h +++ b/include/client.h @@ -303,11 +303,8 @@ struct ListClient { unsigned int hash_indice; unsigned int users_min, users_max; + time_t created_min, created_max, topic_min, topic_max; int operspy; - - /* It would be nice to add other modifiers, - * but not for 1.1 --nenolod - */ }; /* diff --git a/modules/m_list.c b/modules/m_list.c index bb3da499..9bb4d5e6 100644 --- a/modules/m_list.c +++ b/modules/m_list.c @@ -141,7 +141,7 @@ static int m_list(struct Client *client_p, struct Client *source_p, int parc, co */ static int mo_list(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - struct ListClient params; + struct ListClient *params; char *p, *args; int i; @@ -152,19 +152,31 @@ static int mo_list(struct Client *client_p, struct Client *source_p, int parc, c return 0; } - /* XXX rather arbitrary -- jilles */ - params.users_min = 3; - params.users_max = INT_MAX; - params.operspy = 0; + /* Single channel. */ + if (parc > 1 && IsChannelName(parv[1])) + { + safelist_channel_named(source_p, parv[1]); + return 0; + } - if (parc > 1 && parv[1] != NULL && !IsChannelName(parv[1])) + /* Multiple channels, possibly with parameters. */ + params = rb_malloc(sizeof(struct ListClient)); + + /* XXX rather arbitrary -- jilles */ + params->users_min = 3; + params->users_max = INT_MAX; + params->operspy = 0; + params->created_min = params->topic_min = + params->created_max = params->topic_max = 0; + + if (parc > 1 && !EmptyString(parv[1])) { args = LOCAL_COPY(parv[1]); /* Cancel out default minimum. */ - params.users_min = 0; + params->users_min = 0; - for (i = 0; i < 2; i++) + for (i = 0; i < 7; i++) { if ((p = strchr(args, ',')) != NULL) *p++ = '\0'; @@ -174,27 +186,69 @@ static int mo_list(struct Client *client_p, struct Client *source_p, int parc, c args++; if (IsDigit(*args)) { - params.users_max = atoi(args); - if (params.users_max == 0) - params.users_max = INT_MAX; + params->users_max = atoi(args); + if (params->users_max == 0) + params->users_max = INT_MAX; else - params.users_max--; + params->users_max--; } - else - params.users_max = INT_MAX; } else if (*args == '>') { args++; if (IsDigit(*args)) - params.users_min = atoi(args) + 1; + params->users_min = atoi(args) + 1; else - params.users_min = 0; + params->users_min = 0; + } + else if (*args == 'C' || *args == 'c') + { + args++; + if (*args == '>') + { + /* Creation time earlier than last x minutes. */ + args++; + if (IsDigit(*args)) + { + params->created_max = rb_current_time() - (60 * atoi(args)); + } + } + else if (*args == '<') + { + /* Creation time within last x minutes. */ + args++; + if (IsDigit(*args)) + { + params->created_min = rb_current_time() - (60 * atoi(args)); + } + } + } + else if (*args == 'T' || *args == 't') + { + args++; + if (*args == '>') + { + /* Topic change time earlier than last x minutes. */ + args++; + if (IsDigit(*args)) + { + params->topic_max = rb_current_time() - (60 * atoi(args)); + } + } + else if (*args == '<') + { + /* Topic change time within last x minutes. */ + args++; + if (IsDigit(*args)) + { + params->topic_min = rb_current_time() - (60 * atoi(args)); + } + } } /* Only accept operspy as the first option. */ else if (*args == '!' && IsOperSpy(source_p) && i == 0) { - params.operspy = 1; + params->operspy = 1; report_operspy(source_p, "LIST", p); } @@ -204,13 +258,8 @@ static int mo_list(struct Client *client_p, struct Client *source_p, int parc, c args = p; } } - else if (parc > 1 && IsChannelName(parv[1])) - { - safelist_channel_named(source_p, parv[1]); - return 0; - } - safelist_client_instantiate(source_p, ¶ms); + safelist_client_instantiate(source_p, params); return 0; } @@ -238,7 +287,7 @@ static int safelist_sendq_exceeded(struct Client *client_p) * safelist_client_instantiate() * * inputs - pointer to Client to be listed, - * struct ListClient to copy for params + * pointer to ListClient for params * outputs - none * side effects - the safelist process begins for a * client. @@ -248,19 +297,10 @@ static int safelist_sendq_exceeded(struct Client *client_p) */ static void safelist_client_instantiate(struct Client *client_p, struct ListClient *params) { - struct ListClient *self; - s_assert(MyClient(client_p)); s_assert(params != NULL); - self = rb_malloc(sizeof(struct ListClient)); - - self->hash_indice = 0; - self->users_min = params->users_min; - self->users_max = params->users_max; - self->operspy = params->operspy; - - client_p->localClient->safelist_data = self; + client_p->localClient->safelist_data = params; sendto_one(client_p, form_str(RPL_LISTSTART), me.name, client_p->name); @@ -357,6 +397,20 @@ static void safelist_one_channel(struct Client *source_p, struct Channel *chptr) || (unsigned int)chptr->members.length > safelist_data->users_max) return; + if (safelist_data->topic_min && chptr->topic_time < safelist_data->topic_min) + return; + + /* If a topic TS is provided, don't show channels without a topic set. */ + if (safelist_data->topic_max && (chptr->topic_time > safelist_data->topic_max + || chptr->topic_time == 0)) + return; + + if (safelist_data->created_min && chptr->channelts < safelist_data->created_min) + return; + + if (safelist_data->created_max && chptr->channelts > safelist_data->created_max) + return; + sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name, (safelist_data->operspy && SecretChannel(chptr)) ? "!" : "", chptr->chname, rb_dlink_list_length(&chptr->members), diff --git a/src/supported.c b/src/supported.c index 936f4cb2..781ac2c3 100644 --- a/src/supported.c +++ b/src/supported.c @@ -317,7 +317,7 @@ init_isupport(void) add_isupport("STATUSMSG", isupport_string, "@+"); add_isupport("CALLERID", isupport_string, "g"); add_isupport("SAFELIST", isupport_string, ""); - add_isupport("ELIST", isupport_string, "U"); + add_isupport("ELIST", isupport_string, "CTU"); add_isupport("CASEMAPPING", isupport_string, "rfc1459"); add_isupport("CHARSET", isupport_string, "ascii"); add_isupport("NICKLEN", isupport_intptr, &nicklen);