[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

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