]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/lists.c
Use correct sender as target for ISUPPORT replies on "VERSION"
[ngircd-alex.git] / src / ngircd / lists.c
index 8e120bfeb16a059bf17d043dd440bd69c587cfe7..b0accd41edb6476a6d85e27567618b65402906dd 100644 (file)
@@ -34,8 +34,6 @@
 #include "exp.h"
 #include "lists.h"
 
-#define MASK_LEN       (2*CLIENT_HOST_LEN)
-
 struct list_elem {
        struct list_elem *next; /** pointer to next list element */
        char mask[MASK_LEN];    /** IRC mask */
@@ -60,13 +58,13 @@ Lists_GetMask(const struct list_elem *e)
  * Get optional "reason" text stored in list element.
  *
  * @param list_elem List element.
- * @return Pointer to "reason" text or NULL.
+ * @return Pointer to "reason" text or empty string ("").
  */
 GLOBAL const char *
 Lists_GetReason(const struct list_elem *e)
 {
        assert(e != NULL);
-       return e->reason;
+       return e->reason ? e->reason : "";
 }
 
 /**
@@ -126,8 +124,16 @@ Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
        assert(h != NULL);
        assert(Mask != NULL);
 
-       if (Lists_CheckDupeMask(h, Mask))
+       e = Lists_CheckDupeMask(h, Mask);
+       if (e) {
+               e->valid_until = ValidUntil;
+               if (Reason) {
+                       if (e->reason)
+                               free(e->reason);
+                       e->reason = strdup(Reason);
+               }
                return true;
+       }
 
        e = Lists_GetFirst(h);
 
@@ -140,10 +146,8 @@ Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
 
        strlcpy(newelem->mask, Mask, sizeof(newelem->mask));
        if (Reason) {
-               newelem->reason = malloc(strlen(Reason) + 1);
-               if (newelem->reason)
-                       strlcpy(newelem->reason, Reason, strlen(Reason) + 1);
-               else
+               newelem->reason = strdup(Reason);
+               if (!newelem->reason)
                        Log(LOG_EMERG,
                            "Can't allocate memory for new list reason text!");
        }
@@ -240,33 +244,29 @@ Lists_Free(struct list_head *head)
  * @param Mask IRC mask to test.
  * @return true if mask is already stored in the list, false otherwise.
  */
-GLOBAL bool
+GLOBAL struct list_elem *
 Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
 {
        struct list_elem *e;
        e = h->first;
        while (e) {
                if (strcasecmp(e->mask, Mask) == 0)
-                       return true;
+                       return e;
                e = e->next;
        }
-       return false;
+       return NULL;
 }
 
 /**
  * Generate a valid IRC mask from "any" string given.
  *
- * Attention: This mask is only valid until the next call to Lists_MakeMask(),
- * because a single global buffer ist used! You have to copy the generated
- * mask to some sane location yourself!
- *
  * @param Pattern Source string to generate an IRC mask for.
- * @return Pointer to global result buffer.
+ * @param mask    Buffer to store the mask.
+ * @param len     Size of the buffer.
  */
-GLOBAL const char *
-Lists_MakeMask(const char *Pattern)
+GLOBAL void
+Lists_MakeMask(const char *Pattern, char *mask, size_t len)
 {
-       static char TheMask[MASK_LEN];
        char *excl, *at;
 
        assert(Pattern != NULL);
@@ -278,31 +278,23 @@ Lists_MakeMask(const char *Pattern)
                excl = NULL;
 
        if (!at && !excl) {
-               /* Neither "!" nor "@" found: use string as nick name */
-               strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
-               strlcat(TheMask, "!*@*", sizeof(TheMask));
-               return TheMask;
-       }
-
-       if (!at && excl) {
+               /* Neither "!" nor "@" found: use string as nickname */
+               strlcpy(mask, Pattern, len - 5);
+               strlcat(mask, "!*@*", len);
+       } else if (!at && excl) {
                /* Domain part is missing */
-               strlcpy(TheMask, Pattern, sizeof(TheMask) - 3);
-               strlcat(TheMask, "@*", sizeof(TheMask));
-               return TheMask;
-       }
-
-       if (at && !excl) {
+               strlcpy(mask, Pattern, len - 3);
+               strlcat(mask, "@*", len);
+       } else if (at && !excl) {
                /* User name is missing */
                *at = '\0'; at++;
-               strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
-               strlcat(TheMask, "!*@", sizeof(TheMask));
-               strlcat(TheMask, at, sizeof(TheMask));
-               return TheMask;
+               strlcpy(mask, Pattern, len - 5);
+               strlcat(mask, "!*@", len);
+               strlcat(mask, at, len);
+       } else {
+               /* All parts (nick, user and domain name) are given */
+               strlcpy(mask, Pattern, len);
        }
-
-       /* All parts (nick, user and domain name) are given */
-       strlcpy(TheMask, Pattern, sizeof(TheMask));
-       return TheMask;
 } /* Lists_MakeMask */
 
 /**
@@ -313,7 +305,22 @@ Lists_MakeMask(const char *Pattern)
  * @return true if client is listed, false if not.
  */
 bool
-Lists_Check( struct list_head *h, CLIENT *Client)
+Lists_Check(struct list_head *h, CLIENT *Client)
+{
+       return Lists_CheckReason(h, Client, NULL, 0);
+}
+
+/**
+ * Check if a client is listed in a list and store the reason.
+ *
+ * @param h      List head.
+ * @param Client Client to check.
+ * @param reason Buffer to store the reason.
+ * @param len    Size of the buffer if reason should be saved.
+ * @return true if client is listed, false if not.
+ */
+bool
+Lists_CheckReason(struct list_head *h, CLIENT *Client, char *reason, size_t len)
 {
        struct list_elem *e, *last, *next;
 
@@ -324,15 +331,9 @@ Lists_Check( struct list_head *h, CLIENT *Client)
 
        while (e) {
                next = e->next;
-               if (e->valid_until > 1 && e->valid_until < time(NULL)) {
-                       /* Entry is expired, delete it */
-                       LogDebug("Deleted \"%s\" from list (expired).",
-                                e->mask);
-                       Lists_Unlink(h, last, e);
-                       e = next;
-                       continue;
-               }
-               if (Match(e->mask, Client_Mask(Client))) {
+               if (Match(e->mask, Client_MaskCloaked(Client))) {
+                       if (len && e->reason)
+                               strlcpy(reason, e->reason, len);
                        if (e->valid_until == 1) {
                                /* Entry is valid only once, delete it */
                                LogDebug("Deleted \"%s\" from list (used).",
@@ -348,4 +349,64 @@ Lists_Check( struct list_head *h, CLIENT *Client)
        return false;
 }
 
+/**
+ * Check list and purge expired entries.
+ *
+ * @param h List head.
+ */
+GLOBAL void
+Lists_Expire(struct list_head *h, const char *ListName)
+{
+       struct list_elem *e, *last, *next;
+       time_t now;
+
+       assert(h != NULL);
+
+       e = h->first;
+       last = NULL;
+       now = time(NULL);
+
+       while (e) {
+               next = e->next;
+               if (e->valid_until > 1 && e->valid_until < now) {
+                       /* Entry is expired, delete it */
+                       if (e->reason)
+                               Log(LOG_INFO,
+                                   "Deleted \"%s\" (\"%s\") from %s list (expired).",
+                                   e->mask, e->reason, ListName);
+                       else
+                               Log(LOG_INFO,
+                                   "Deleted \"%s\" from %s list (expired).",
+                                   e->mask, ListName);
+                       Lists_Unlink(h, last, e);
+                       e = next;
+                       continue;
+               }
+               last = e;
+               e = next;
+       }
+}
+
+/**
+ * Return the number of entries of a list.
+ *
+ * @param h List head.
+ * @return Number of items.
+ */
+GLOBAL unsigned long
+Lists_Count(struct list_head *h)
+{
+       struct list_elem *e;
+       unsigned long count = 0;
+
+       assert(h != NULL);
+
+       e = h->first;
+       while (e) {
+               count++;
+               e = e->next;
+       }
+       return count;
+}
+
 /* -eof- */