[BACK]Return to lists.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/lists.c, Revision 1.1

1.1     ! tomglok     1: /*
        !             2:  * ngIRCd -- The Next Generation IRC Daemon
        !             3:  * Copyright (c)2001-2018 Alexander Barton (alex@barton.de) and Contributors.
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify
        !             6:  * it under the terms of the GNU General Public License as published by
        !             7:  * the Free Software Foundation; either version 2 of the License, or
        !             8:  * (at your option) any later version.
        !             9:  * Please read the file COPYING, README and AUTHORS for more information.
        !            10:  */
        !            11:
        !            12: #include "portab.h"
        !            13:
        !            14: /**
        !            15:  * @file
        !            16:  * Management of IRC lists: ban, invite, etc.
        !            17:  */
        !            18:
        !            19: #include <assert.h>
        !            20: #include <stdlib.h>
        !            21: #include <string.h>
        !            22: #include <strings.h>
        !            23: #include <time.h>
        !            24:
        !            25: #include "conn.h"
        !            26: #include "log.h"
        !            27: #include "match.h"
        !            28:
        !            29: #include "lists.h"
        !            30:
        !            31: struct list_elem {
        !            32:        struct list_elem *next; /** pointer to next list element */
        !            33:        char mask[MASK_LEN];    /** IRC mask */
        !            34:        char *reason;           /** Optional "reason" text */
        !            35:        time_t valid_until;     /** 0: unlimited; t(>0): until t */
        !            36:        bool onlyonce;
        !            37: };
        !            38:
        !            39: /**
        !            40:  * Get IRC mask stored in list element.
        !            41:  *
        !            42:  * @param e List element.
        !            43:  * @return Pointer to IRC mask
        !            44:  */
        !            45: GLOBAL const char *
        !            46: Lists_GetMask(const struct list_elem *e)
        !            47: {
        !            48:        assert(e != NULL);
        !            49:        return e->mask;
        !            50: }
        !            51:
        !            52: /**
        !            53:  * Get optional "reason" text stored in list element.
        !            54:  *
        !            55:  * @param e List element.
        !            56:  * @return Pointer to "reason" text or empty string ("").
        !            57:  */
        !            58: GLOBAL const char *
        !            59: Lists_GetReason(const struct list_elem *e)
        !            60: {
        !            61:        assert(e != NULL);
        !            62:        return e->reason ? e->reason : "";
        !            63: }
        !            64:
        !            65: /**
        !            66:  * Get "validity" value stored in list element.
        !            67:  *
        !            68:  * @param e List element.
        !            69:  * @return Validity: 0=unlimited, >0 until this time stamp.
        !            70:  */
        !            71: GLOBAL time_t
        !            72: Lists_GetValidity(const struct list_elem *e)
        !            73: {
        !            74:        assert(e != NULL);
        !            75:        return e->valid_until;
        !            76: }
        !            77:
        !            78: /**
        !            79:  * Get "onlyonce" value stored in list element.
        !            80:  *
        !            81:  * @param e List element.
        !            82:  * @return True if the element was stored for single use, false otherwise.
        !            83:  */
        !            84: GLOBAL bool
        !            85: Lists_GetOnlyOnce(const struct list_elem *e)
        !            86: {
        !            87:        assert(e != NULL);
        !            88:        return e->onlyonce;
        !            89: }
        !            90:
        !            91: /**
        !            92:  * Get first list element of a list.
        !            93:  *
        !            94:  * @param h List head.
        !            95:  * @return Pointer to first list element.
        !            96:  */
        !            97: GLOBAL struct list_elem*
        !            98: Lists_GetFirst(const struct list_head *h)
        !            99: {
        !           100:        assert(h != NULL);
        !           101:        return h->first;
        !           102: }
        !           103:
        !           104: /**
        !           105:  * Get next list element of a list.
        !           106:  *
        !           107:  * @param e Current list element.
        !           108:  * @return Pointer to next list element.
        !           109:  */
        !           110: GLOBAL struct list_elem*
        !           111: Lists_GetNext(const struct list_elem *e)
        !           112: {
        !           113:        assert(e != NULL);
        !           114:        return e->next;
        !           115: }
        !           116:
        !           117: /**
        !           118:  * Add a new mask to a list.
        !           119:  *
        !           120:  * @param h List head.
        !           121:  * @param Mask The IRC mask to add to the list.
        !           122:  * @param ValidUntil 0: unlimited, 1: only once, t>1: until given time_t.
        !           123:  * @param Reason Reason string or NULL, if no reason should be saved.
        !           124:  * @return true on success, false otherwise.
        !           125:  */
        !           126: bool
        !           127: Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
        !           128:          const char *Reason, bool OnlyOnce)
        !           129: {
        !           130:        struct list_elem *e, *newelem;
        !           131:
        !           132:        assert(h != NULL);
        !           133:        assert(Mask != NULL);
        !           134:
        !           135:        e = Lists_CheckDupeMask(h, Mask);
        !           136:        if (e) {
        !           137:                e->valid_until = ValidUntil;
        !           138:                if (Reason) {
        !           139:                        if (e->reason)
        !           140:                                free(e->reason);
        !           141:                        e->reason = strdup(Reason);
        !           142:                }
        !           143:                return true;
        !           144:        }
        !           145:
        !           146:        e = Lists_GetFirst(h);
        !           147:
        !           148:        newelem = malloc(sizeof(struct list_elem));
        !           149:        if (!newelem) {
        !           150:                Log(LOG_EMERG,
        !           151:                    "Can't allocate memory for new list entry!");
        !           152:                return false;
        !           153:        }
        !           154:
        !           155:        strlcpy(newelem->mask, Mask, sizeof(newelem->mask));
        !           156:        if (Reason) {
        !           157:                newelem->reason = strdup(Reason);
        !           158:                if (!newelem->reason)
        !           159:                        Log(LOG_EMERG,
        !           160:                            "Can't allocate memory for new list reason text!");
        !           161:        }
        !           162:        else
        !           163:                newelem->reason = NULL;
        !           164:        newelem->valid_until = ValidUntil;
        !           165:        newelem->onlyonce = OnlyOnce;
        !           166:        newelem->next = e;
        !           167:        h->first = newelem;
        !           168:
        !           169:        return true;
        !           170: }
        !           171:
        !           172: /**
        !           173:  * Delete a list element from a list.
        !           174:  *
        !           175:  * @param h List head.
        !           176:  * @param p Pointer to previous list element or NULL, if there is none.
        !           177:  * @param victim List element to delete.
        !           178:  */
        !           179: static void
        !           180: Lists_Unlink(struct list_head *h, struct list_elem *p, struct list_elem *victim)
        !           181: {
        !           182:        assert(victim != NULL);
        !           183:        assert(h != NULL);
        !           184:
        !           185:        if (p)
        !           186:                p->next = victim->next;
        !           187:        else
        !           188:                h->first = victim->next;
        !           189:
        !           190:        if (victim->reason)
        !           191:                free(victim->reason);
        !           192:
        !           193:        free(victim);
        !           194: }
        !           195:
        !           196: /**
        !           197:  * Delete a given IRC mask from a list.
        !           198:  *
        !           199:  * @param h List head.
        !           200:  * @param Mask IRC mask to delete from the list.
        !           201:  */
        !           202: GLOBAL void
        !           203: Lists_Del(struct list_head *h, const char *Mask)
        !           204: {
        !           205:        struct list_elem *e, *last, *victim;
        !           206:
        !           207:        assert(h != NULL);
        !           208:        assert(Mask != NULL);
        !           209:
        !           210:        last = NULL;
        !           211:        e = Lists_GetFirst(h);
        !           212:        while (e) {
        !           213:                if (strcasecmp(e->mask, Mask) == 0) {
        !           214:                        LogDebug("Deleted \"%s\" from list", e->mask);
        !           215:                        victim = e;
        !           216:                        e = victim->next;
        !           217:                        Lists_Unlink(h, last, victim);
        !           218:                        continue;
        !           219:                }
        !           220:                last = e;
        !           221:                e = e->next;
        !           222:        }
        !           223: }
        !           224:
        !           225: /**
        !           226:  * Free a complete list.
        !           227:  *
        !           228:  * @param head List head.
        !           229:  */
        !           230: GLOBAL void
        !           231: Lists_Free(struct list_head *head)
        !           232: {
        !           233:        struct list_elem *e, *victim;
        !           234:
        !           235:        assert(head != NULL);
        !           236:
        !           237:        e = head->first;
        !           238:        head->first = NULL;
        !           239:        while (e) {
        !           240:                LogDebug("Deleted \"%s\" from list" , e->mask);
        !           241:                victim = e;
        !           242:                e = e->next;
        !           243:                if (victim->reason)
        !           244:                        free(victim->reason);
        !           245:                free(victim);
        !           246:        }
        !           247: }
        !           248:
        !           249: /**
        !           250:  * Check if an IRC mask is already contained in a list.
        !           251:  *
        !           252:  * @param h List head.
        !           253:  * @param Mask IRC mask to test.
        !           254:  * @return true if mask is already stored in the list, false otherwise.
        !           255:  */
        !           256: GLOBAL struct list_elem *
        !           257: Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
        !           258: {
        !           259:        struct list_elem *e;
        !           260:        e = h->first;
        !           261:        while (e) {
        !           262:                if (strcasecmp(e->mask, Mask) == 0)
        !           263:                        return e;
        !           264:                e = e->next;
        !           265:        }
        !           266:        return NULL;
        !           267: }
        !           268:
        !           269: /**
        !           270:  * Generate a valid IRC mask from "any" string given.
        !           271:  *
        !           272:  * @param Pattern Source string to generate an IRC mask for.
        !           273:  * @param mask    Buffer to store the mask.
        !           274:  * @param len     Size of the buffer.
        !           275:  */
        !           276: GLOBAL void
        !           277: Lists_MakeMask(const char *Pattern, char *mask, size_t len)
        !           278: {
        !           279:        char *excl, *at;
        !           280:
        !           281:        assert(Pattern != NULL);
        !           282:
        !           283:        excl = strchr(Pattern, '!');
        !           284:        at = strchr(Pattern, '@');
        !           285:
        !           286:        if (at && at < excl)
        !           287:                excl = NULL;
        !           288:
        !           289:        if (!at && !excl) {
        !           290:                /* Neither "!" nor "@" found: use string as nickname */
        !           291:                strlcpy(mask, Pattern, len - 5);
        !           292:                strlcat(mask, "!*@*", len);
        !           293:        } else if (!at && excl) {
        !           294:                /* Domain part is missing */
        !           295:                strlcpy(mask, Pattern, len - 3);
        !           296:                strlcat(mask, "@*", len);
        !           297:        } else if (at && !excl) {
        !           298:                /* User name is missing */
        !           299:                *at = '\0'; at++;
        !           300:                strlcpy(mask, Pattern, len - 5);
        !           301:                strlcat(mask, "!*@", len);
        !           302:                strlcat(mask, at, len);
        !           303:                at--; *at = '@';
        !           304:        } else {
        !           305:                /* All parts (nick, user and domain name) are given */
        !           306:                strlcpy(mask, Pattern, len);
        !           307:        }
        !           308: } /* Lists_MakeMask */
        !           309:
        !           310: /**
        !           311:  * Check if a client is listed in a list.
        !           312:  *
        !           313:  * @param h List head.
        !           314:  * @param Client Client to check.
        !           315:  * @return true if client is listed, false if not.
        !           316:  */
        !           317: bool
        !           318: Lists_Check(struct list_head *h, CLIENT *Client)
        !           319: {
        !           320:        return Lists_CheckReason(h, Client, NULL, 0);
        !           321: }
        !           322:
        !           323: /**
        !           324:  * Check if a client is listed in a list and store the reason.
        !           325:  *
        !           326:  * @param h      List head.
        !           327:  * @param Client Client to check.
        !           328:  * @param reason Buffer to store the reason.
        !           329:  * @param len    Size of the buffer if reason should be saved.
        !           330:  * @return true if client is listed, false if not.
        !           331:  */
        !           332: bool
        !           333: Lists_CheckReason(struct list_head *h, CLIENT *Client, char *reason, size_t len)
        !           334: {
        !           335:        struct list_elem *e, *last, *next;
        !           336:
        !           337:        assert(h != NULL);
        !           338:
        !           339:        e = h->first;
        !           340:        last = NULL;
        !           341:
        !           342:        while (e) {
        !           343:                next = e->next;
        !           344:                if (MatchCaseInsensitive(e->mask, Client_MaskCloaked(Client))) {
        !           345:                        if (len && e->reason)
        !           346:                                strlcpy(reason, e->reason, len);
        !           347:                        if (e->onlyonce) {
        !           348:                                /* Entry is valid only once, delete it */
        !           349:                                LogDebug("Deleted \"%s\" from list (used).",
        !           350:                                         e->mask);
        !           351:                                Lists_Unlink(h, last, e);
        !           352:                        }
        !           353:                        return true;
        !           354:                }
        !           355:                last = e;
        !           356:                e = next;
        !           357:        }
        !           358:
        !           359:        return false;
        !           360: }
        !           361:
        !           362: /**
        !           363:  * Check list and purge expired entries.
        !           364:  *
        !           365:  * @param h List head.
        !           366:  */
        !           367: GLOBAL void
        !           368: Lists_Expire(struct list_head *h, const char *ListName)
        !           369: {
        !           370:        struct list_elem *e, *last, *next;
        !           371:        time_t now;
        !           372:
        !           373:        assert(h != NULL);
        !           374:
        !           375:        e = h->first;
        !           376:        last = NULL;
        !           377:        now = time(NULL);
        !           378:
        !           379:        while (e) {
        !           380:                next = e->next;
        !           381:                if (e->valid_until > 0 && e->valid_until < now) {
        !           382:                        /* Entry is expired, delete it */
        !           383:                        if (e->reason)
        !           384:                                Log(LOG_NOTICE|LOG_snotice,
        !           385:                                    "Deleted \"%s\" (\"%s\") from %s list (expired).",
        !           386:                                    e->mask, e->reason, ListName);
        !           387:                        else
        !           388:                                Log(LOG_NOTICE|LOG_snotice,
        !           389:                                    "Deleted \"%s\" from %s list (expired).",
        !           390:                                    e->mask, ListName);
        !           391:                        Lists_Unlink(h, last, e);
        !           392:                        e = next;
        !           393:                        continue;
        !           394:                }
        !           395:                last = e;
        !           396:                e = next;
        !           397:        }
        !           398: }
        !           399:
        !           400: /**
        !           401:  * Return the number of entries of a list.
        !           402:  *
        !           403:  * @param h List head.
        !           404:  * @return Number of items.
        !           405:  */
        !           406: GLOBAL unsigned long
        !           407: Lists_Count(struct list_head *h)
        !           408: {
        !           409:        struct list_elem *e;
        !           410:        unsigned long count = 0;
        !           411:
        !           412:        assert(h != NULL);
        !           413:
        !           414:        e = h->first;
        !           415:        while (e) {
        !           416:                count++;
        !           417:                e = e->next;
        !           418:        }
        !           419:        return count;
        !           420: }
        !           421:
        !           422: /* -eof- */

CVSweb