added basic ssl support to ircu
[ircu2.10.12-pk.git] / ircd / m_list.c
index 6007f7e172d0b56e709ce0f0916d4ea63cb3d2ee..b43ab1575762b3330d2886a6327169d43a8d9cec 100644 (file)
  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
  *                    non-NULL pointers.
  */
-#if 0
-/*
- * No need to include handlers.h here the signatures must match
- * and we don't need to force a rebuild of all the handlers everytime
- * we add a new one to the list. --Bleep
- */
-#include "handlers.h"
-#endif /* 0 */
+#include "config.h"
+
 #include "channel.h"
 #include "client.h"
 #include "hash.h"
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
+#include "s_bsd.h"
 #include "send.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <stdlib.h>
 #include <string.h>
 
@@ -115,10 +110,11 @@ static struct ListingArgs la_init = {
   0,                          /* min_time */
   4294967295U,                /* max_users */
   0,                          /* min_users */
-  0,                          /* topic_limits */
+  0,                          /* flags */
   2147483647,                 /* max_topic_time */
   0,                          /* min_topic_time */
-  0                           /* chptr */
+  0,                          /* bucket */
+  {0}                         /* wildcard */
 };
 
 static struct ListingArgs la_default = {
@@ -126,10 +122,11 @@ static struct ListingArgs la_default = {
   0,                          /* min_time */
   4294967295U,                /* max_users */
   0,                          /* min_users */
-  0,                          /* topic_limits */
+  0,                          /* flags */
   2147483647,                 /* max_topic_time */
   0,                          /* min_topic_time */
-  0                           /* chptr */
+  0,                          /* bucket */
+  {0}                         /* wildcard */
 };
 
 static int
@@ -143,7 +140,7 @@ show_usage(struct Client *sptr)
   send_reply(sptr, RPL_LISTUSAGE,
             "Usage: \002/QUOTE LIST\002 \037parameters\037");
   send_reply(sptr, RPL_LISTUSAGE,
-            "Where \037parameters\037 is a space or comma seperated "
+            "Where \037parameters\037 is a space or comma separated "
             "list of one or more of:");
   send_reply(sptr, RPL_LISTUSAGE,
             " \002<\002\037max_users\037    ; Show all channels with less "
@@ -164,8 +161,22 @@ show_usage(struct Client *sptr)
             " \002T>\002\037min_minutes\037 ; Channels with a topic last "
             "set more than \037min_minutes\037 ago.");
   send_reply(sptr, RPL_LISTUSAGE,
-            "Example: LIST <3,>1,C<10,T>0  ; 2 users, younger than 10 "
-            "min., topic set.");
+            " \037pattern\037       ; Channels with names matching "
+             "\037pattern\037. ");
+  send_reply(sptr, RPL_LISTUSAGE,
+            " !\037pattern\037      ; Channels with names not "
+             "matching \037pattern\037. ");
+  send_reply(sptr, RPL_LISTUSAGE, "Note: Patterns may contain * and ?. "
+             "You may only give one pattern match constraint.");
+  if (IsAnOper(sptr)) {
+    send_reply(sptr, RPL_LISTUSAGE,
+               " \002S\002             ; Show secret channels.");
+    send_reply(sptr, RPL_LISTUSAGE,
+               " \002M\002             ; Show channel modes.");
+  }
+  send_reply(sptr, RPL_LISTUSAGE,
+            "Example: LIST <3,>1,C<10,T>0,#a*  ; 2 users, younger than 10 "
+            "min., topic set., starts with #a");
 
   return LPARAM_ERROR; /* return error condition */
 }
@@ -177,6 +188,7 @@ param_parse(struct Client *sptr, const char *param, struct ListingArgs *args,
   int is_time = 0;
   char dir;
   unsigned int val;
+  char *tmp1, *tmp2;
 
   assert(0 != args);
 
@@ -188,7 +200,7 @@ param_parse(struct Client *sptr, const char *param, struct ListingArgs *args,
     case 'T':
     case 't':
       is_time++;
-      args->topic_limits = 1;
+      args->flags |= LISTARG_TOPICLIMITS;
       /*FALLTHROUGH*/
 
     case 'C':
@@ -211,8 +223,11 @@ param_parse(struct Client *sptr, const char *param, struct ListingArgs *args,
       if (*param != ',' && *param != ' ' && *param != '\0') /* check syntax */
        return show_usage(sptr);
 
-      if (is_time && val < 80000000) /* Toggle UTC/offset */
-       val = TStime() - val * 60;
+      if (is_time && val < 80000000) {
+        /* Convert age to timestamp and reverse direction */
+        val = TStime() - val * 60;
+        dir = (dir == '>') ? '<' : '>';
+      }
       
       switch (is_time) {
       case 0: /* number of users on channel */
@@ -222,28 +237,91 @@ param_parse(struct Client *sptr, const char *param, struct ListingArgs *args,
          args->min_users = val;
        break;
 
-      case 1: /* channel topic */
+      case 1: /* channel creation time */
        if (dir == '<')
-         args->min_topic_time = val;
+         args->max_time = val;
        else
-         args->max_topic_time = val;
+         args->min_time = val;
        break;
 
-      case 2: /* channel creation time */
+      case 2: /* channel topic */
        if (dir == '<')
-         args->min_time = val;
+         args->max_topic_time = val;
        else
-         args->max_time = val;
+         args->min_topic_time = val;
        break;
       }
       break;
 
-    default: /* channel name? */
+    case 'S':
+    case 's':
+      if (!IsAnOper(sptr) || !HasPriv(sptr, PRIV_LIST_CHAN))
+        return show_usage(sptr);
+
+      args->flags |= LISTARG_SHOWSECRET;
+      param++;
+
+      if (*param != ',' && *param != ' ' && *param != '\0') /* check syntax */
+        return show_usage(sptr);
+      break;
+
+    case 'M':
+    case 'm':
+      if (!IsAnOper(sptr) || !HasPriv(sptr, PRIV_LIST_CHAN))
+        return show_usage(sptr);
+
+      args->flags |= LISTARG_SHOWMODES;
+      param++;
+
+      if (*param != ',' && *param != ' ' && *param != '\0') /* check syntax */
+        return show_usage(sptr);
+      break;
+
+    default:
+      /* It might be a wildcard... */
+      if (strchr(param, '*') ||
+          strchr(param, '?'))
+      {
+        if (param[0] == '!')
+        {
+          param++;
+          args->flags |= LISTARG_NEGATEWILDCARD;
+        }
+
+        /* Only one wildcard allowed... */
+        if (args->wildcard[0] != 0)
+          return show_usage(sptr);
+
+        /* If its not going to match anything, don't bother. */
+        if (param[0] != '*' &&
+            param[0] != '?' &&
+            param[0] != '#' &&
+            param[0] != '&')
+          return show_usage(sptr);
+
+        tmp1 = strchr(param, ',');
+        tmp2 = strchr(param, ' ');
+        if (tmp2 && (!tmp1 || (tmp2 < tmp1)))
+          tmp1 = tmp2;
+        
+        if (tmp1)
+          *tmp1++ = 0;
+
+        ircd_strncpy(args->wildcard, param, CHANNELLEN-1);
+        args->wildcard[CHANNELLEN-1] = 0;
+
+        if (tmp1 == NULL)
+          return LPARAM_SUCCESS;
+
+        param = tmp1;
+        continue;
+      }
+
+      /* channel name? */
       if (!permit_chan || !IsChannelName(param))
        return show_usage(sptr);
 
       return LPARAM_CHANNEL;
-      break;
     }
 
     if (!*param) /* hit end of string? */
@@ -281,12 +359,13 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
   if (cli_listing(sptr))            /* Already listing ? */
   {
-    cli_listing(sptr)->chptr->mode.mode &= ~MODE_LISTED;
+    if (cli_listing(sptr))
     MyFree(cli_listing(sptr));
     cli_listing(sptr) = 0;
     send_reply(sptr, RPL_LISTEND);
-    if (parc < 2)
-      return 0;                 /* Let LIST abort a listing. */
+    update_write(sptr);
+    if (parc < 2 || 0 == ircd_strcmp("STOP", parv[1]))
+      return 0;                 /* Let LIST or LIST STOP abort a listing. */
   }
 
   if (parc < 2)                 /* No arguments given to /LIST ? */
@@ -295,10 +374,9 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     args = la_init; /* initialize argument to blank slate */
 
     for (param = 1; parv[param]; param++) { /* process each parameter */
-      switch (param_parse(sptr, parv[param], &args, parc != 2)) {
+      switch (param_parse(sptr, parv[param], &args, parc == 2)) {
       case LPARAM_ERROR: /* error encountered, usage already sent, return */
        return 0;
-       break;
 
       case LPARAM_CHANNEL: /* show channel instead */
        show_channels++;
@@ -320,14 +398,8 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       cli_listing(sptr) = (struct ListingArgs*) MyMalloc(sizeof(struct ListingArgs));
       assert(0 != cli_listing(sptr));
       memcpy(cli_listing(sptr), &args, sizeof(struct ListingArgs));
-      if ((cli_listing(sptr)->chptr = GlobalChannelList)) {
-        int m = GlobalChannelList->mode.mode & MODE_LISTED;
-        list_next_channels(sptr, 64);
-        GlobalChannelList->mode.mode |= m;
-        return 0;
-      }
-      MyFree(cli_listing(sptr));
-      cli_listing(sptr) = 0;
+      list_next_channels(sptr);
+      return 0;
     }
     send_reply(sptr, RPL_LISTEND);
     return 0;
@@ -336,7 +408,10 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
   {
     chptr = FindChannel(name);
-    if (chptr && ShowChannel(sptr, chptr) && cli_user(sptr))
+    if (!chptr)
+        continue;
+    if (ShowChannel(sptr, chptr)
+        || (IsAnOper(sptr) && HasPriv(sptr, PRIV_LIST_CHAN)))
       send_reply(sptr, RPL_LIST, chptr->chname,
                 chptr->users - number_of_zombies(chptr), chptr->topic);
   }