added gnutls backend and moved backend code into new files
[ircu2.10.12-pk.git] / ircd / m_list.c
index 471743b838062d2bf1dc3e2fe67d15d62361b04c..b43ab1575762b3330d2886a6327169d43a8d9cec 100644 (file)
@@ -110,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 = {
@@ -121,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
@@ -138,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 "
@@ -158,12 +160,23 @@ show_usage(struct Client *sptr)
   send_reply(sptr, RPL_LISTUSAGE,
             " \002T>\002\037min_minutes\037 ; Channels with a topic last "
             "set more than \037min_minutes\037 ago.");
-  if (IsAnOper(sptr))
+  send_reply(sptr, RPL_LISTUSAGE,
+            " \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  ; 2 users, younger than 10 "
-            "min., topic set.");
+            "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 */
 }
@@ -175,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);
 
@@ -209,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 */
@@ -220,25 +237,25 @@ 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;
 
     case 'S':
     case 's':
-      if (!IsAnOper(sptr))
+      if (!IsAnOper(sptr) || !HasPriv(sptr, PRIV_LIST_CHAN))
         return show_usage(sptr);
 
       args->flags |= LISTARG_SHOWSECRET;
@@ -248,12 +265,63 @@ param_parse(struct Client *sptr, const char *param, struct ListingArgs *args,
         return show_usage(sptr);
       break;
 
-    default: /* channel name? */
+    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? */
@@ -291,6 +359,7 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
   if (cli_listing(sptr))            /* Already listing ? */
   {
+    if (cli_listing(sptr))
     MyFree(cli_listing(sptr));
     cli_listing(sptr) = 0;
     send_reply(sptr, RPL_LISTEND);
@@ -308,7 +377,6 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       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++;
@@ -340,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);
   }