added gnutls backend and moved backend code into new files
[ircu2.10.12-pk.git] / ircd / hash.c
index 7d335022e7e9ee13137cedf6fafc4e8e015b5b2e..aa264ddb158500431bc94d4830e4d9b00e48a4bc 100644 (file)
 #include "hash.h"
 #include "client.h"
 #include "channel.h"
+#include "ircd_alloc.h"
 #include "ircd_chattr.h"
+#include "ircd_log.h"
+#include "ircd_reply.h"
 #include "ircd_string.h"
 #include "ircd.h"
+#include "match.h"
 #include "msg.h"
+#include "numeric.h"
 #include "random.h"
 #include "send.h"
 #include "struct.h"
 #include "sys.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
@@ -69,20 +74,14 @@ void init_hash(void)
     crc32hash[ii] = rand;
   }
 
-  /* Now reorder the hash table.  To make it case-insensitive, skip
-   * upper-case letters, and have lower-case letters write to the
-   * corresponding upper-case character.
-   */
+  /* Now reorder the hash table. */
   for (ii = 0, rand = 0; ii < 256; ii++)
   {
-    char ch = ii + CHAR_MIN;
-    if (ch != ToLower(ch))
-      continue;
     if (!rand)
       rand = ircrandom();
     poly = ii + rand % (256 - ii);
     jj = crc32hash[ii];
-    crc32hash[ToUpper(ch) - CHAR_MIN] = crc32hash[ii] = crc32hash[poly];
+    crc32hash[ii] = crc32hash[poly];
     crc32hash[poly] = jj;
     rand >>= 8;
   }
@@ -97,9 +96,9 @@ typedef unsigned int HASHREGS;
  */
 static HASHREGS strhash(const char *n)
 {
-  HASHREGS hash = crc32hash[*n++ & 255];
+  HASHREGS hash = crc32hash[ToLower(*n++) & 255];
   while (*n)
-    hash = (hash >> 8) ^ crc32hash[(hash ^ *n++) & 255];
+    hash = (hash >> 8) ^ crc32hash[(hash ^ ToLower(*n++)) & 255];
   return hash % HASHSIZE;
 }
 
@@ -110,7 +109,7 @@ static HASHREGS strhash(const char *n)
  * I avoided introducing new variables to do the work myself and I did let
  * the optimizer play with more free registers, actual tests proved this
  * solution to be faster than doing things like tmp2=tmp->hnext... and then
- * use tmp2 myself wich would have given less freedom to the optimizer.
+ * use tmp2 myself which would have given less freedom to the optimizer.
  */
 
 /** Prepend a client to the appropriate hash bucket.
@@ -409,3 +408,74 @@ void clearNickJupes(void)
   for (i = 0; i < JUPEHASHSIZE; i++)
     jupeTable[i][0] = '\000';
 }
+
+/** Report all nick jupes to a user.
+ * @param[in] to Client requesting statistics.
+ * @param[in] sd Stats descriptor for request (ignored).
+ * @param[in] param Extra parameter from user (ignored).
+ */
+void
+stats_nickjupes(struct Client* to, const struct StatDesc* sd, char* param)
+{
+  int i;
+  for (i = 0; i < JUPEHASHSIZE; i++)
+    if (jupeTable[i][0])
+      send_reply(to, RPL_STATSJLINE, jupeTable[i]);
+}
+
+/** Send more channels to a client in mid-LIST.
+ * @param[in] cptr Client to send the list to.
+ */
+void list_next_channels(struct Client *cptr)
+{
+  struct ListingArgs *args;
+  struct Channel *chptr;
+
+  /* Walk consecutive buckets until we hit the end. */
+  for (args = cli_listing(cptr); args->bucket < HASHSIZE; args->bucket++)
+  {
+    /* Send all the matching channels in the bucket. */
+    for (chptr = channelTable[args->bucket]; chptr; chptr = chptr->hnext)
+    {
+      if (chptr->users > args->min_users
+          && chptr->users < args->max_users
+          && chptr->creationtime > args->min_time
+          && chptr->creationtime < args->max_time
+          && (!args->wildcard[0] || (args->flags & LISTARG_NEGATEWILDCARD) ||
+              (!match(args->wildcard, chptr->chname)))
+          && (!(args->flags & LISTARG_NEGATEWILDCARD) ||
+              match(args->wildcard, chptr->chname))
+          && (!(args->flags & LISTARG_TOPICLIMITS)
+              || (chptr->topic[0]
+                  && chptr->topic_time > args->min_topic_time
+                  && chptr->topic_time < args->max_topic_time))
+          && ((args->flags & LISTARG_SHOWSECRET)
+              || ShowChannel(cptr, chptr)))
+      {
+        if (args->flags & LISTARG_SHOWMODES) {
+          char modebuf[MODEBUFLEN];
+          char parabuf[MODEBUFLEN];
+
+          modebuf[0] = modebuf[1] = parabuf[0] = '\0';
+          channel_modes(cptr, modebuf, parabuf, sizeof(parabuf), chptr, NULL);
+          send_reply(cptr, RPL_LIST | SND_EXPLICIT, "%s %u %s %s :%s",
+                     chptr->chname, chptr->users, modebuf, parabuf, chptr->topic);
+        } else {
+          send_reply(cptr, RPL_LIST, chptr->chname, chptr->users, chptr->topic);
+        }
+      }
+    }
+    /* If, at the end of the bucket, client sendq is more than half
+     * full, stop. */
+    if (MsgQLength(&cli_sendQ(cptr)) > cli_max_sendq(cptr) / 2)
+      break;
+  }
+
+  /* If we did all buckets, clean the client and send RPL_LISTEND. */
+  if (args->bucket >= HASHSIZE)
+  {
+    MyFree(cli_listing(cptr));
+    cli_listing(cptr) = NULL;
+    send_reply(cptr, RPL_LISTEND);
+  }
+}