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

Annotation of ircnowd/src/ngircd/channel.c, Revision 1.1.1.1

1.1       tomglok     1: /*
                      2:  * ngIRCd -- The Next Generation IRC Daemon
                      3:  * Copyright (c)2001-2014 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: #define __channel_c__
                     13:
                     14: #include "portab.h"
                     15:
                     16: /**
                     17:  * @file
                     18:  * Channel management
                     19:  */
                     20:
                     21: #include <assert.h>
                     22: #include <stdlib.h>
                     23: #include <string.h>
                     24: #include <errno.h>
                     25: #include <stdio.h>
                     26: #include <strings.h>
                     27: #include <time.h>
                     28:
                     29: #include "conn-func.h"
                     30:
                     31: #include "channel.h"
                     32:
                     33: #include "irc-write.h"
                     34: #include "conf.h"
                     35: #include "hash.h"
                     36: #include "log.h"
                     37: #include "messages.h"
                     38: #include "match.h"
                     39: #include "parse.h"
                     40: #include "irc-mode.h"
                     41:
                     42: #define REMOVE_PART 0
                     43: #define REMOVE_QUIT 1
                     44: #define REMOVE_KICK 2
                     45:
                     46: static CHANNEL *My_Channels;
                     47: static CL2CHAN *My_Cl2Chan;
                     48:
                     49: static CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client ));
                     50: static CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client ));
                     51: static bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer ));
                     52: static CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan ));
                     53: static CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan ));
                     54: static void Delete_Channel PARAMS(( CHANNEL *Chan ));
                     55: static void Free_Channel PARAMS(( CHANNEL *Chan ));
                     56: static void Set_KeyFile PARAMS((CHANNEL *Chan, const char *KeyFile));
                     57:
                     58:
                     59: GLOBAL void
                     60: Channel_Init( void )
                     61: {
                     62:        My_Channels = NULL;
                     63:        My_Cl2Chan = NULL;
                     64: } /* Channel_Init */
                     65:
                     66:
                     67: GLOBAL struct list_head *
                     68: Channel_GetListBans(CHANNEL *c)
                     69: {
                     70:        assert(c != NULL);
                     71:        return &c->list_bans;
                     72: }
                     73:
                     74:
                     75: GLOBAL struct list_head *
                     76: Channel_GetListExcepts(CHANNEL *c)
                     77: {
                     78:        assert(c != NULL);
                     79:        return &c->list_excepts;
                     80: }
                     81:
                     82:
                     83: GLOBAL struct list_head *
                     84: Channel_GetListInvites(CHANNEL *c)
                     85: {
                     86:        assert(c != NULL);
                     87:        return &c->list_invites;
                     88: }
                     89:
                     90:
                     91: /**
                     92:  * Generate predefined persistent channels and &SERVER
                     93:  */
                     94: GLOBAL void
                     95: Channel_InitPredefined( void )
                     96: {
                     97:        CHANNEL *new_chan;
                     98:        REQUEST Req;
                     99:        const struct Conf_Channel *conf_chan;
                    100:        char *c;
                    101:        char modes[COMMAND_LEN], name[CHANNEL_NAME_LEN];
                    102:        size_t i, n, channel_count = array_length(&Conf_Channels, sizeof(*conf_chan));
                    103:
                    104:        conf_chan = array_start(&Conf_Channels);
                    105:
                    106:        assert(channel_count == 0 || conf_chan != NULL);
                    107:
                    108:        for (i = 0; i < channel_count; i++, conf_chan++) {
                    109:                if (!conf_chan->name[0])
                    110:                        continue;
                    111:                if (!Channel_IsValidName(conf_chan->name)) {
                    112:                        Log(LOG_ERR,
                    113:                            "Can't create pre-defined channel: invalid name: \"%s\"",
                    114:                            conf_chan->name);
                    115:                        continue;
                    116:                }
                    117:
                    118:                new_chan = Channel_Search(conf_chan->name);
                    119:                if (new_chan) {
                    120:                        Log(LOG_INFO,
                    121:                            "Can't create pre-defined channel \"%s\": name already in use.",
                    122:                            conf_chan->name);
                    123:                        Set_KeyFile(new_chan, conf_chan->keyfile);
                    124:                        continue;
                    125:                }
                    126:
                    127:                new_chan = Channel_Create(conf_chan->name);
                    128:                if (!new_chan) {
                    129:                        Log(LOG_ERR, "Can't create pre-defined channel \"%s\"!",
                    130:                                                        conf_chan->name);
                    131:                        continue;
                    132:                }
                    133:                Channel_ModeAdd(new_chan, 'P');
                    134:
                    135:                if (conf_chan->topic[0])
                    136:                        Channel_SetTopic(new_chan, NULL, conf_chan->topic);
                    137:
                    138:                /* Evaluate modes strings with fake requests */
                    139:                if (conf_chan->modes_num) {
                    140:                        /* Prepare fake request structure */
                    141:                        strlcpy(name, conf_chan->name, sizeof(name));
                    142:                        Log(LOG_INFO, "Evaluating predefined channel modes for \"%s\".", name);
                    143:                        Req.argv[0] = name;
                    144:                        Req.prefix = Client_ID(Client_ThisServer());
                    145:                        Req.command = "MODE";
                    146:
                    147:                        /* Iterate over channel modes strings */
                    148:                        for (n = 0; n < conf_chan->modes_num; n++) {
                    149:                                Req.argc = 1;
                    150:                                strlcpy(modes, conf_chan->modes[n], sizeof(modes));
                    151:                                Log(LOG_DEBUG, "Evaluate \"MODE %s %s\".", name, modes);
                    152:                                c = strtok(modes, " ");
                    153:                                while (c && Req.argc < 15) {
                    154:                                        Req.argv[Req.argc++] = c;
                    155:                                        c = strtok(0, " ");
                    156:                                }
                    157:
                    158:                                if (Req.argc > 1) {
                    159:                                        /* Handling of legacy "Key" and "MaxUsers" settings:
                    160:                                         * Enforce setting the respective mode(s), to support
                    161:                                         * the legacy "Mode = kl" notation, which was valid but
                    162:                                         * is an invalid MODE string: key and limit are missing!
                    163:                                         * So set them manually when "k" or "l" are detected in
                    164:                                         * the first MODE parameter ... */
                    165:                                        if (Req.argc > 1 && strchr(Req.argv[1], 'k')) {
                    166:                                                Channel_SetKey(new_chan, conf_chan->key);
                    167:                                                Channel_ModeAdd(new_chan, 'k');
                    168:                                        }
                    169:                                        if (strchr(Req.argv[1], 'l')) {
                    170:                                                Channel_SetMaxUsers(new_chan, conf_chan->maxusers);
                    171:                                                Channel_ModeAdd(new_chan, 'l');
                    172:                                        }
                    173:
                    174:                                        IRC_MODE(Client_ThisServer(), &Req);
                    175:                                }
                    176:
                    177:                                /* Original channel modes srings are no longer needed */
                    178:                                free(conf_chan->modes[n]);
                    179:                        }
                    180:                }
                    181:
                    182:                Set_KeyFile(new_chan, conf_chan->keyfile);
                    183:
                    184:                Log(LOG_INFO,
                    185:                    "Created pre-defined channel \"%s\", mode \"%s\" (key \"%s\", limit %d).",
                    186:                    new_chan->name, new_chan->modes, new_chan->key,
                    187:                    new_chan->maxusers);
                    188:        }
                    189:        if (channel_count)
                    190:                array_free(&Conf_Channels);
                    191:
                    192:        /* Make sure the local &SERVER channel exists */
                    193:        if (!Channel_Search("&SERVER")) {
                    194:                new_chan = Channel_Create("&SERVER");
                    195:                if (new_chan) {
                    196:                        Channel_SetModes(new_chan, "mnPt");
                    197:                        Channel_SetTopic(new_chan, Client_ThisServer(),
                    198:                                         "Server Messages");
                    199:                } else
                    200:                        Log(LOG_ERR, "Failed to create \"&SERVER\" channel!");
                    201:        } else
                    202:                LogDebug("Required channel \"&SERVER\" already exists, ok.");
                    203: } /* Channel_InitPredefined */
                    204:
                    205:
                    206: static void
                    207: Free_Channel(CHANNEL *chan)
                    208: {
                    209:        array_free(&chan->topic);
                    210:        array_free(&chan->keyfile);
                    211:        Lists_Free(&chan->list_bans);
                    212:        Lists_Free(&chan->list_excepts);
                    213:        Lists_Free(&chan->list_invites);
                    214:
                    215:        free(chan);
                    216: }
                    217:
                    218:
                    219: GLOBAL void
                    220: Channel_Exit( void )
                    221: {
                    222:        CHANNEL *c, *c_next;
                    223:        CL2CHAN *cl2chan, *cl2chan_next;
                    224:
                    225:        /* free struct Channel */
                    226:        c = My_Channels;
                    227:        while (c) {
                    228:                c_next = c->next;
                    229:                Free_Channel(c);
                    230:                c = c_next;
                    231:        }
                    232:
                    233:        /* Free Channel allocation table */
                    234:        cl2chan = My_Cl2Chan;
                    235:        while (cl2chan) {
                    236:                cl2chan_next = cl2chan->next;
                    237:                free(cl2chan);
                    238:                cl2chan = cl2chan_next;
                    239:        }
                    240: } /* Channel_Exit */
                    241:
                    242:
                    243: /**
                    244:  * Join Channel
                    245:  * This function lets a client join a channel.  First, the function
                    246:  * checks that the specified channel name is valid and that the client
                    247:  * isn't already a member.  If the specified channel doesn't exist,
                    248:  * a new channel is created.  Client is added to channel by function
                    249:  * Add_Client().
                    250:  */
                    251: GLOBAL bool
                    252: Channel_Join( CLIENT *Client, const char *Name )
                    253: {
                    254:        CHANNEL *chan;
                    255:
                    256:        assert(Client != NULL);
                    257:        assert(Name != NULL);
                    258:
                    259:        /* Check that the channel name is valid */
                    260:        if (! Channel_IsValidName(Name)) {
                    261:                IRC_WriteErrClient(Client, ERR_NOSUCHCHANNEL_MSG,
                    262:                                   Client_ID(Client), Name);
                    263:                return false;
                    264:        }
                    265:
                    266:        chan = Channel_Search(Name);
                    267:        if(chan) {
                    268:                /* Check if the client is already in the channel */
                    269:                if (Get_Cl2Chan(chan, Client))
                    270:                        return false;
                    271:        } else {
                    272:                /* If the specified channel does not exist, the channel
                    273:                 * is now created */
                    274:                chan = Channel_Create(Name);
                    275:                if (!chan)
                    276:                        return false;
                    277:        }
                    278:
                    279:        /* Add user to Channel */
                    280:        if (! Add_Client(chan, Client))
                    281:                return false;
                    282:
                    283:        return true;
                    284: } /* Channel_Join */
                    285:
                    286:
                    287: /**
                    288:  * Part client from channel.
                    289:  * This function lets a client part from a channel. First, the function checks
                    290:  * if the channel exists and the client is a member of it and sends out
                    291:  * appropriate error messages if not. The real work is done by the function
                    292:  * Remove_Client().
                    293:  */
                    294: GLOBAL bool
                    295: Channel_Part(CLIENT * Client, CLIENT * Origin, const char *Name, const char *Reason)
                    296: {
                    297:        CHANNEL *chan;
                    298:
                    299:        assert(Client != NULL);
                    300:        assert(Name != NULL);
                    301:        assert(Reason != NULL);
                    302:
                    303:        /* Check that specified channel exists */
                    304:        chan = Channel_Search(Name);
                    305:        if (!chan) {
                    306:                IRC_WriteErrClient(Client, ERR_NOSUCHCHANNEL_MSG,
                    307:                                   Client_ID(Client), Name);
                    308:                return false;
                    309:        }
                    310:
                    311:        /* Check that the client is in the channel */
                    312:        if (!Get_Cl2Chan(chan, Client)) {
                    313:                IRC_WriteErrClient(Client, ERR_NOTONCHANNEL_MSG,
                    314:                                   Client_ID(Client), Name);
                    315:                return false;
                    316:        }
                    317:
                    318:        if (Conf_MorePrivacy)
                    319:                Reason = "";
                    320:
                    321:        /* Part client from channel */
                    322:        if (!Remove_Client(REMOVE_PART, chan, Client, Origin, Reason, true))
                    323:                return false;
                    324:        else
                    325:                return true;
                    326: } /* Channel_Part */
                    327:
                    328:
                    329: /**
                    330:  * Kick user from Channel
                    331:  */
                    332: GLOBAL void
                    333: Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name,
                    334:             const char *Reason )
                    335: {
                    336:        CHANNEL *chan;
                    337:        bool can_kick = false;
                    338:
                    339:        assert(Peer != NULL);
                    340:        assert(Target != NULL);
                    341:        assert(Origin != NULL);
                    342:        assert(Name != NULL);
                    343:        assert(Reason != NULL);
                    344:
                    345:        /* Check that channel exists */
                    346:        chan = Channel_Search( Name );
                    347:        if (!chan) {
                    348:                IRC_WriteErrClient(Origin, ERR_NOSUCHCHANNEL_MSG,
                    349:                                   Client_ID(Origin), Name);
                    350:                return;
                    351:        }
                    352:
                    353:        if (Client_Type(Peer) != CLIENT_SERVER &&
                    354:            Client_Type(Origin) != CLIENT_SERVICE) {
                    355:                /* Check that user is on the specified channel */
                    356:                if (!Channel_IsMemberOf(chan, Origin)) {
                    357:                        IRC_WriteErrClient(Origin, ERR_NOTONCHANNEL_MSG,
                    358:                                           Client_ID(Origin), Name);
                    359:                        return;
                    360:                }
                    361:        }
                    362:
                    363:        /* Check that the client to be kicked is on the specified channel */
                    364:        if (!Channel_IsMemberOf(chan, Target)) {
                    365:                IRC_WriteErrClient(Origin, ERR_USERNOTINCHANNEL_MSG,
                    366:                                   Client_ID(Origin), Client_ID(Target), Name );
                    367:                return;
                    368:        }
                    369:
                    370:        if(Client_Type(Peer) == CLIENT_USER) {
                    371:                /* Channel mode 'Q' and user mode 'q' on target: nobody but
                    372:                 * IRC Operators and servers can kick the target user */
                    373:                if ((Channel_HasMode(chan, 'Q')
                    374:                     || Client_HasMode(Target, 'q')
                    375:                     || Client_Type(Target) == CLIENT_SERVICE)
                    376:                    && !Client_HasMode(Origin, 'o')) {
                    377:                        IRC_WriteErrClient(Origin, ERR_KICKDENY_MSG,
                    378:                                           Client_ID(Origin), Name,
                    379:                                           Client_ID(Target));
                    380:                        return;
                    381:                }
                    382:
                    383:                /* Check if client has the rights to kick target */
                    384:
                    385:                /* Owner can kick everyone */
                    386:                if (Channel_UserHasMode(chan, Peer, 'q'))
                    387:                        can_kick = true;
                    388:
                    389:                /* Admin can't kick owner */
                    390:                else if (Channel_UserHasMode(chan, Peer, 'a') &&
                    391:                    !Channel_UserHasMode(chan, Target, 'q'))
                    392:                        can_kick = true;
                    393:
                    394:                /* Op can't kick owner | admin */
                    395:                else if (Channel_UserHasMode(chan, Peer, 'o') &&
                    396:                    !Channel_UserHasMode(chan, Target, 'q') &&
                    397:                    !Channel_UserHasMode(chan, Target, 'a'))
                    398:                        can_kick = true;
                    399:
                    400:                /* Half Op can't kick owner | admin | op */
                    401:                else if (Channel_UserHasMode(chan, Peer, 'h') &&
                    402:                    !Channel_UserHasMode(chan, Target, 'q') &&
                    403:                    !Channel_UserHasMode(chan, Target, 'a') &&
                    404:                    !Channel_UserHasMode(chan, Target, 'o'))
                    405:                        can_kick = true;
                    406:
                    407:                /* IRC operators & IRCd with OperCanMode enabled
                    408:                 * can kick anyways regardless of privilege */
                    409:                else if(Client_HasMode(Origin, 'o') && Conf_OperCanMode)
                    410:                    can_kick = true;
                    411:
                    412:                if(!can_kick) {
                    413:                        IRC_WriteErrClient(Origin, ERR_CHANOPPRIVTOOLOW_MSG,
                    414:                                           Client_ID(Origin), Name);
                    415:                        return;
                    416:                }
                    417:        }
                    418:
                    419:        /* Kick Client from channel */
                    420:        Remove_Client( REMOVE_KICK, chan, Target, Origin, Reason, true);
                    421: } /* Channel_Kick */
                    422:
                    423:
                    424: GLOBAL void
                    425: Channel_Quit( CLIENT *Client, const char *Reason )
                    426: {
                    427:        CHANNEL *c, *next_c;
                    428:
                    429:        assert( Client != NULL );
                    430:        assert( Reason != NULL );
                    431:
                    432:        if (Conf_MorePrivacy)
                    433:                Reason = "";
                    434:
                    435:        IRC_WriteStrRelatedPrefix( Client, Client, false, "QUIT :%s", Reason );
                    436:
                    437:        c = My_Channels;
                    438:        while( c )
                    439:        {
                    440:                next_c = c->next;
                    441:                Remove_Client( REMOVE_QUIT, c, Client, Client, Reason, false );
                    442:                c = next_c;
                    443:        }
                    444: } /* Channel_Quit */
                    445:
                    446:
                    447: /**
                    448:  * Get number of channels this server knows and that are "visible" to
                    449:  * the given client. If no client is given, all channels will be counted.
                    450:  *
                    451:  * @param Client The client to check or NULL.
                    452:  * @return Number of channels visible to the client.
                    453:  */
                    454: GLOBAL unsigned long
                    455: Channel_CountVisible (CLIENT *Client)
                    456: {
                    457:        CHANNEL *c;
                    458:        unsigned long count = 0;
                    459:
                    460:        c = My_Channels;
                    461:        while(c) {
                    462:                if (Client) {
                    463:                        if (!Channel_HasMode(c, 's')
                    464:                            || Channel_IsMemberOf(c, Client))
                    465:                                count++;
                    466:                } else
                    467:                        count++;
                    468:                c = c->next;
                    469:        }
                    470:        return count;
                    471: }
                    472:
                    473:
                    474: GLOBAL unsigned long
                    475: Channel_MemberCount( CHANNEL *Chan )
                    476: {
                    477:        CL2CHAN *cl2chan;
                    478:        unsigned long count = 0;
                    479:
                    480:        assert( Chan != NULL );
                    481:
                    482:        cl2chan = My_Cl2Chan;
                    483:        while( cl2chan )
                    484:        {
                    485:                if( cl2chan->channel == Chan ) count++;
                    486:                cl2chan = cl2chan->next;
                    487:        }
                    488:        return count;
                    489: } /* Channel_MemberCount */
                    490:
                    491:
                    492: GLOBAL int
                    493: Channel_CountForUser( CLIENT *Client )
                    494: {
                    495:        /* Count number of channels a user is member of. */
                    496:
                    497:        CL2CHAN *cl2chan;
                    498:        int count = 0;
                    499:
                    500:        assert( Client != NULL );
                    501:
                    502:        cl2chan = My_Cl2Chan;
                    503:        while( cl2chan )
                    504:        {
                    505:                if( cl2chan->client == Client ) count++;
                    506:                cl2chan = cl2chan->next;
                    507:        }
                    508:
                    509:        return count;
                    510: } /* Channel_CountForUser */
                    511:
                    512:
                    513: GLOBAL const char *
                    514: Channel_Name( const CHANNEL *Chan )
                    515: {
                    516:        assert( Chan != NULL );
                    517:        return Chan->name;
                    518: } /* Channel_Name */
                    519:
                    520:
                    521: GLOBAL char *
                    522: Channel_Modes( CHANNEL *Chan )
                    523: {
                    524:        assert( Chan != NULL );
                    525:        return Chan->modes;
                    526: } /* Channel_Modes */
                    527:
                    528:
                    529: GLOBAL bool
                    530: Channel_HasMode( CHANNEL *Chan, char Mode )
                    531: {
                    532:        assert( Chan != NULL );
                    533:        return strchr( Chan->modes, Mode ) != NULL;
                    534: } /* Channel_HasMode */
                    535:
                    536:
                    537: GLOBAL char *
                    538: Channel_Key( CHANNEL *Chan )
                    539: {
                    540:        assert( Chan != NULL );
                    541:        return Chan->key;
                    542: } /* Channel_Key */
                    543:
                    544:
                    545: GLOBAL unsigned long
                    546: Channel_MaxUsers( CHANNEL *Chan )
                    547: {
                    548:        assert( Chan != NULL );
                    549:        return Chan->maxusers;
                    550: } /* Channel_MaxUsers */
                    551:
                    552:
                    553: GLOBAL CHANNEL *
                    554: Channel_First( void )
                    555: {
                    556:        return My_Channels;
                    557: } /* Channel_First */
                    558:
                    559:
                    560: GLOBAL CHANNEL *
                    561: Channel_Next( CHANNEL *Chan )
                    562: {
                    563:        assert( Chan != NULL );
                    564:        return Chan->next;
                    565: } /* Channel_Next */
                    566:
                    567:
                    568: GLOBAL CHANNEL *
                    569: Channel_Search( const char *Name )
                    570: {
                    571:        /* Search channel structure */
                    572:
                    573:        CHANNEL *c;
                    574:        UINT32 search_hash;
                    575:
                    576:        assert( Name != NULL );
                    577:
                    578:        search_hash = Hash( Name );
                    579:        c = My_Channels;
                    580:        while( c )
                    581:        {
                    582:                if( search_hash == c->hash )
                    583:                {
                    584:                        /* hash hit */
                    585:                        if( strcasecmp( Name, c->name ) == 0 ) return c;
                    586:                }
                    587:                c = c->next;
                    588:        }
                    589:        return NULL;
                    590: } /* Channel_Search */
                    591:
                    592:
                    593: GLOBAL CL2CHAN *
                    594: Channel_FirstMember( CHANNEL *Chan )
                    595: {
                    596:        assert( Chan != NULL );
                    597:        return Get_First_Cl2Chan( NULL, Chan );
                    598: } /* Channel_FirstMember */
                    599:
                    600:
                    601: GLOBAL CL2CHAN *
                    602: Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan )
                    603: {
                    604:        assert( Chan != NULL );
                    605:        assert( Cl2Chan != NULL );
                    606:        return Get_Next_Cl2Chan( Cl2Chan->next, NULL, Chan );
                    607: } /* Channel_NextMember */
                    608:
                    609:
                    610: GLOBAL CL2CHAN *
                    611: Channel_FirstChannelOf( CLIENT *Client )
                    612: {
                    613:        assert( Client != NULL );
                    614:        return Get_First_Cl2Chan( Client, NULL );
                    615: } /* Channel_FirstChannelOf */
                    616:
                    617:
                    618: GLOBAL CL2CHAN *
                    619: Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan )
                    620: {
                    621:        assert( Client != NULL );
                    622:        assert( Cl2Chan != NULL );
                    623:        return Get_Next_Cl2Chan( Cl2Chan->next, Client, NULL );
                    624: } /* Channel_NextChannelOf */
                    625:
                    626:
                    627: GLOBAL CLIENT *
                    628: Channel_GetClient( CL2CHAN *Cl2Chan )
                    629: {
                    630:        assert( Cl2Chan != NULL );
                    631:        return Cl2Chan->client;
                    632: } /* Channel_GetClient */
                    633:
                    634:
                    635: GLOBAL CHANNEL *
                    636: Channel_GetChannel( CL2CHAN *Cl2Chan )
                    637: {
                    638:        assert( Cl2Chan != NULL );
                    639:        return Cl2Chan->channel;
                    640: } /* Channel_GetChannel */
                    641:
                    642:
                    643: GLOBAL bool
                    644: Channel_IsValidName( const char *Name )
                    645: {
                    646:        assert( Name != NULL );
                    647:
                    648: #ifdef STRICT_RFC
                    649:        if (strlen(Name) <= 1)
                    650:                return false;
                    651: #endif
                    652:        if (strchr("#&+", Name[0]) == NULL)
                    653:                return false;
                    654:        if (strlen(Name) >= CHANNEL_NAME_LEN)
                    655:                return false;
                    656:
                    657:        return Name[strcspn(Name, " ,:\007")] == 0;
                    658: } /* Channel_IsValidName */
                    659:
                    660:
                    661: GLOBAL bool
                    662: Channel_ModeAdd( CHANNEL *Chan, char Mode )
                    663: {
                    664:        /* set Mode.
                    665:         * If the channel already had this mode, return false.
                    666:         * If the channel mode was newly set return true.
                    667:         */
                    668:
                    669:        char x[2];
                    670:
                    671:        assert( Chan != NULL );
                    672:
                    673:        x[0] = Mode; x[1] = '\0';
                    674:        if( ! Channel_HasMode( Chan, x[0] ))
                    675:        {
                    676:                /* Channel does not have this mode yet, set it */
                    677:                strlcat( Chan->modes, x, sizeof( Chan->modes ));
                    678:                return true;
                    679:        }
                    680:        else return false;
                    681: } /* Channel_ModeAdd */
                    682:
                    683:
                    684: GLOBAL bool
                    685: Channel_ModeDel( CHANNEL *Chan, char Mode )
                    686: {
                    687:        /* Delete mode.
                    688:         * if the mode was removed return true.
                    689:         * if the channel did not have the mode, return false.
                    690:        */
                    691:        char *p;
                    692:
                    693:        assert( Chan != NULL );
                    694:
                    695:        p = strchr( Chan->modes, Mode );
                    696:        if( ! p ) return false;
                    697:
                    698:        /* Channel has mode -> delete */
                    699:        while( *p )
                    700:        {
                    701:                *p = *(p + 1);
                    702:                p++;
                    703:        }
                    704:        return true;
                    705: } /* Channel_ModeDel */
                    706:
                    707:
                    708: GLOBAL bool
                    709: Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, char Mode )
                    710: {
                    711:        /* Set Channel-User-Mode.
                    712:         * if mode was newly set, return true.
                    713:         * if the User already had this channel-mode, return false.
                    714:         */
                    715:
                    716:        CL2CHAN *cl2chan;
                    717:        char x[2];
                    718:
                    719:        assert( Chan != NULL );
                    720:        assert( Client != NULL );
                    721:
                    722:        cl2chan = Get_Cl2Chan( Chan, Client );
                    723:        assert( cl2chan != NULL );
                    724:
                    725:        x[0] = Mode; x[1] = '\0';
                    726:        if( ! strchr( cl2chan->modes, x[0] ))
                    727:        {
                    728:                /* mode not set, -> set it */
                    729:                strlcat( cl2chan->modes, x, sizeof( cl2chan->modes ));
                    730:                return true;
                    731:        }
                    732:        else return false;
                    733: } /* Channel_UserModeAdd */
                    734:
                    735:
                    736: GLOBAL bool
                    737: Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, char Mode )
                    738: {
                    739:        /* Delete Channel-User-Mode.
                    740:         * If Mode was removed, return true.
                    741:         * If User did not have the Channel-Mode, return false.
                    742:         */
                    743:
                    744:        CL2CHAN *cl2chan;
                    745:        char *p;
                    746:
                    747:        assert( Chan != NULL );
                    748:        assert( Client != NULL );
                    749:
                    750:        cl2chan = Get_Cl2Chan( Chan, Client );
                    751:        assert( cl2chan != NULL );
                    752:
                    753:        p = strchr( cl2chan->modes, Mode );
                    754:        if( ! p ) return false;
                    755:
                    756:        /* Client has Mode -> delete */
                    757:        while( *p )
                    758:        {
                    759:                *p = *(p + 1);
                    760:                p++;
                    761:        }
                    762:        return true;
                    763: } /* Channel_UserModeDel */
                    764:
                    765:
                    766: GLOBAL char *
                    767: Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
                    768: {
                    769:        /* return Users' Channel-Modes */
                    770:
                    771:        CL2CHAN *cl2chan;
                    772:
                    773:        assert( Chan != NULL );
                    774:        assert( Client != NULL );
                    775:
                    776:        cl2chan = Get_Cl2Chan( Chan, Client );
                    777:        assert( cl2chan != NULL );
                    778:
                    779:        return cl2chan->modes;
                    780: } /* Channel_UserModes */
                    781:
                    782:
                    783: GLOBAL bool
                    784: Channel_UserHasMode( CHANNEL *Chan, CLIENT *Client, char Mode )
                    785: {
                    786:        return strchr(Channel_UserModes(Chan, Client), Mode) != NULL;
                    787: } /* Channel_UserHasMode */
                    788:
                    789:
                    790: GLOBAL bool
                    791: Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
                    792: {
                    793:        /* Test if Client is on Channel Chan */
                    794:
                    795:        assert( Chan != NULL );
                    796:        assert( Client != NULL );
                    797:        return Get_Cl2Chan(Chan, Client) != NULL;
                    798: } /* Channel_IsMemberOf */
                    799:
                    800:
                    801: GLOBAL char *
                    802: Channel_Topic( CHANNEL *Chan )
                    803: {
                    804:        char *ret;
                    805:        assert( Chan != NULL );
                    806:        ret = array_start(&Chan->topic);
                    807:        return ret ? ret : "";
                    808: } /* Channel_Topic */
                    809:
                    810:
                    811: #ifndef STRICT_RFC
                    812:
                    813: GLOBAL unsigned int
                    814: Channel_TopicTime(CHANNEL *Chan)
                    815: {
                    816:        assert(Chan != NULL);
                    817:        return (unsigned int) Chan->topic_time;
                    818: } /* Channel_TopicTime */
                    819:
                    820:
                    821: GLOBAL char *
                    822: Channel_TopicWho(CHANNEL *Chan)
                    823: {
                    824:        assert(Chan != NULL);
                    825:        return Chan->topic_who;
                    826: } /* Channel_TopicWho */
                    827:
                    828:
                    829: GLOBAL unsigned int
                    830: Channel_CreationTime(CHANNEL *Chan)
                    831: {
                    832:        assert(Chan != NULL);
                    833:        return (unsigned int) Chan->creation_time;
                    834: } /* Channel_CreationTime */
                    835:
                    836: #endif
                    837:
                    838:
                    839: GLOBAL void
                    840: Channel_SetTopic(CHANNEL *Chan, CLIENT *Client, const char *Topic)
                    841: {
                    842:        size_t len;
                    843:        assert( Chan != NULL );
                    844:        assert( Topic != NULL );
                    845:
                    846:        len = strlen(Topic);
                    847:        if (len < array_bytes(&Chan->topic))
                    848:                array_free(&Chan->topic);
                    849:
                    850:        if (len >= COMMAND_LEN || !array_copyb(&Chan->topic, Topic, len+1))
                    851:                Log(LOG_WARNING, "could not set new Topic \"%s\" on %s: %s",
                    852:                                        Topic, Chan->name, strerror(errno));
                    853: #ifndef STRICT_RFC
                    854:        Chan->topic_time = time(NULL);
                    855:        if (Client != NULL && Client_Type(Client) != CLIENT_SERVER)
                    856:                strlcpy(Chan->topic_who, Client_ID(Client),
                    857:                        sizeof Chan->topic_who);
                    858:        else
                    859:                strlcpy(Chan->topic_who, DEFAULT_TOPIC_ID,
                    860:                        sizeof Chan->topic_who);
                    861: #else
                    862:        (void) Client;
                    863: #endif
                    864: } /* Channel_SetTopic */
                    865:
                    866:
                    867: GLOBAL void
                    868: Channel_SetModes( CHANNEL *Chan, const char *Modes )
                    869: {
                    870:        assert( Chan != NULL );
                    871:        assert( Modes != NULL );
                    872:
                    873:        strlcpy( Chan->modes, Modes, sizeof( Chan->modes ));
                    874: } /* Channel_SetModes */
                    875:
                    876:
                    877: GLOBAL void
                    878: Channel_SetKey( CHANNEL *Chan, const char *Key )
                    879: {
                    880:        assert( Chan != NULL );
                    881:        assert( Key != NULL );
                    882:
                    883:        strlcpy( Chan->key, Key, sizeof( Chan->key ));
                    884:        LogDebug("Channel %s: Key is now \"%s\".", Chan->name, Chan->key );
                    885: } /* Channel_SetKey */
                    886:
                    887:
                    888: GLOBAL void
                    889: Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
                    890: {
                    891:        assert( Chan != NULL );
                    892:
                    893:        Chan->maxusers = Count;
                    894:        LogDebug("Channel %s: Member limit is now %lu.", Chan->name, Chan->maxusers );
                    895: } /* Channel_SetMaxUsers */
                    896:
                    897:
                    898: /**
                    899:  * Check if a client is allowed to send to a specific channel.
                    900:  *
                    901:  * @param Chan The channel to check.
                    902:  * @param From The client that wants to send.
                    903:  * @return true if the client is allowed to send, false otherwise.
                    904:  */
                    905: static bool
                    906: Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
                    907: {
                    908:        bool is_member, has_voice, is_halfop, is_op, is_chanadmin, is_owner;
                    909:
                    910:        is_member = has_voice = is_halfop = is_op = is_chanadmin = is_owner = false;
                    911:
                    912:        /* The server itself always can send messages :-) */
                    913:        if (Client_ThisServer() == From)
                    914:                return true;
                    915:
                    916:        if (Channel_IsMemberOf(Chan, From)) {
                    917:                is_member = true;
                    918:                if (Channel_UserHasMode(Chan, From, 'v'))
                    919:                        has_voice = true;
                    920:                if (Channel_UserHasMode(Chan, From, 'h'))
                    921:                        is_halfop = true;
                    922:                if (Channel_UserHasMode(Chan, From, 'o'))
                    923:                        is_op = true;
                    924:                if (Channel_UserHasMode(Chan, From, 'a'))
                    925:                        is_chanadmin = true;
                    926:                if (Channel_UserHasMode(Chan, From, 'q'))
                    927:                        is_owner = true;
                    928:        }
                    929:
                    930:        /*
                    931:         * Is the client allowed to write to channel?
                    932:         *
                    933:         * If channel mode n set: non-members cannot send to channel.
                    934:         * If channel mode m set: need voice.
                    935:         */
                    936:        if (Channel_HasMode(Chan, 'n') && !is_member)
                    937:                return false;
                    938:
                    939:        if (Channel_HasMode(Chan, 'M') && !Client_HasMode(From, 'R')
                    940:            && !Client_HasMode(From, 'o'))
                    941:                return false;
                    942:
                    943:        if (has_voice || is_halfop || is_op || is_chanadmin || is_owner)
                    944:                return true;
                    945:
                    946:        if (Channel_HasMode(Chan, 'm'))
                    947:                return false;
                    948:
                    949:        if (Lists_Check(&Chan->list_excepts, From))
                    950:                return true;
                    951:
                    952:        return !Lists_Check(&Chan->list_bans, From);
                    953: }
                    954:
                    955:
                    956: GLOBAL bool
                    957: Channel_Write(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Command,
                    958:              bool SendErrors, const char *Text)
                    959: {
                    960:        if (!Can_Send_To_Channel(Chan, From)) {
                    961:                if (! SendErrors)
                    962:                        return CONNECTED;       /* no error, see RFC 2812 */
                    963:                if (Channel_HasMode(Chan, 'M'))
                    964:                        return IRC_WriteErrClient(From, ERR_NEEDREGGEDNICK_MSG,
                    965:                                                  Client_ID(From), Channel_Name(Chan));
                    966:                else
                    967:                        return IRC_WriteErrClient(From, ERR_CANNOTSENDTOCHAN_MSG,
                    968:                                          Client_ID(From), Channel_Name(Chan));
                    969:        }
                    970:
                    971:        if (Client_Conn(From) > NONE)
                    972:                Conn_UpdateIdle(Client_Conn(From));
                    973:
                    974:        IRC_WriteStrChannelPrefix(Client, Chan, From, true, "%s %s :%s",
                    975:                                  Command, Channel_Name(Chan), Text);
                    976:        return CONNECTED;
                    977: }
                    978:
                    979:
                    980: GLOBAL CHANNEL *
                    981: Channel_Create( const char *Name )
                    982: {
                    983:        /* Create new CHANNEL structure and add it to linked list */
                    984:        CHANNEL *c;
                    985:
                    986:        assert( Name != NULL );
                    987:
                    988:        c = (CHANNEL *)malloc( sizeof( CHANNEL ));
                    989:        if( ! c )
                    990:        {
                    991:                Log( LOG_EMERG, "Can't allocate memory! [New_Chan]" );
                    992:                return NULL;
                    993:        }
                    994:        memset( c, 0, sizeof( CHANNEL ));
                    995:        strlcpy( c->name, Name, sizeof( c->name ));
                    996:        c->hash = Hash( c->name );
                    997:        c->next = My_Channels;
                    998: #ifndef STRICT_RFC
                    999:        c->creation_time = time(NULL);
                   1000: #endif
                   1001:        My_Channels = c;
                   1002:        LogDebug("Created new channel structure for \"%s\".", Name);
                   1003:        return c;
                   1004: } /* Channel_Create */
                   1005:
                   1006:
                   1007: static CL2CHAN *
                   1008: Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client )
                   1009: {
                   1010:        CL2CHAN *cl2chan;
                   1011:
                   1012:        assert( Chan != NULL );
                   1013:        assert( Client != NULL );
                   1014:
                   1015:        cl2chan = My_Cl2Chan;
                   1016:        while( cl2chan )
                   1017:        {
                   1018:                if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) return cl2chan;
                   1019:                cl2chan = cl2chan->next;
                   1020:        }
                   1021:        return NULL;
                   1022: } /* Get_Cl2Chan */
                   1023:
                   1024:
                   1025: static CL2CHAN *
                   1026: Add_Client( CHANNEL *Chan, CLIENT *Client )
                   1027: {
                   1028:        CL2CHAN *cl2chan;
                   1029:
                   1030:        assert( Chan != NULL );
                   1031:        assert( Client != NULL );
                   1032:
                   1033:        /* Create new CL2CHAN structure */
                   1034:        cl2chan = (CL2CHAN *)malloc( sizeof( CL2CHAN ));
                   1035:        if( ! cl2chan )
                   1036:        {
                   1037:                Log( LOG_EMERG, "Can't allocate memory! [Add_Client]" );
                   1038:                return NULL;
                   1039:        }
                   1040:        cl2chan->channel = Chan;
                   1041:        cl2chan->client = Client;
                   1042:        strcpy( cl2chan->modes, "" );
                   1043:
                   1044:        /* concatenate */
                   1045:        cl2chan->next = My_Cl2Chan;
                   1046:        My_Cl2Chan = cl2chan;
                   1047:
                   1048:        LogDebug("User \"%s\" joined channel \"%s\".", Client_Mask(Client), Chan->name);
                   1049:
                   1050:        return cl2chan;
                   1051: } /* Add_Client */
                   1052:
                   1053:
                   1054: static bool
                   1055: Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer )
                   1056: {
                   1057:        CL2CHAN *cl2chan, *last_cl2chan;
                   1058:        CHANNEL *c;
                   1059:
                   1060:        assert( Chan != NULL );
                   1061:        assert( Client != NULL );
                   1062:        assert( Origin != NULL );
                   1063:        assert( Reason != NULL );
                   1064:
                   1065:        /* Do not inform other servers if the channel is local to this server,
                   1066:         * regardless of what the caller requested! */
                   1067:        if(InformServer)
                   1068:                InformServer = !Channel_IsLocal(Chan);
                   1069:
                   1070:        last_cl2chan = NULL;
                   1071:        cl2chan = My_Cl2Chan;
                   1072:        while( cl2chan )
                   1073:        {
                   1074:                if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) break;
                   1075:                last_cl2chan = cl2chan;
                   1076:                cl2chan = cl2chan->next;
                   1077:        }
                   1078:        if( ! cl2chan ) return false;
                   1079:
                   1080:        c = cl2chan->channel;
                   1081:        assert( c != NULL );
                   1082:
                   1083:        /* maintain cl2chan list */
                   1084:        if( last_cl2chan ) last_cl2chan->next = cl2chan->next;
                   1085:        else My_Cl2Chan = cl2chan->next;
                   1086:        free( cl2chan );
                   1087:
                   1088:        switch( Type )
                   1089:        {
                   1090:                case REMOVE_QUIT:
                   1091:                        /* QUIT: other servers have already been notified,
                   1092:                         * see Client_Destroy(); so only inform other clients
                   1093:                         * in same channel. */
                   1094:                        assert( InformServer == false );
                   1095:                        LogDebug("User \"%s\" left channel \"%s\" (%s).",
                   1096:                                        Client_Mask( Client ), c->name, Reason );
                   1097:                        break;
                   1098:                case REMOVE_KICK:
                   1099:                        /* User was KICKed: inform other servers (public
                   1100:                         * channels) and all users in the channel */
                   1101:                        if( InformServer )
                   1102:                                IRC_WriteStrServersPrefix( Client_NextHop( Origin ),
                   1103:                                        Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason);
                   1104:                        IRC_WriteStrChannelPrefix(Client, c, Origin, false, "KICK %s %s :%s",
                   1105:                                                        c->name, Client_ID( Client ), Reason );
                   1106:                        if ((Client_Conn(Client) > NONE) &&
                   1107:                                        (Client_Type(Client) == CLIENT_USER))
                   1108:                        {
                   1109:                                IRC_WriteStrClientPrefix(Client, Origin, "KICK %s %s :%s",
                   1110:                                                                c->name, Client_ID( Client ), Reason);
                   1111:                        }
                   1112:                        LogDebug("User \"%s\" has been kicked off \"%s\" by \"%s\": %s.",
                   1113:                                Client_Mask( Client ), c->name, Client_ID(Origin), Reason);
                   1114:                        break;
                   1115:                default: /* PART */
                   1116:                        if (Conf_MorePrivacy)
                   1117:                                Reason = "";
                   1118:
                   1119:                        if (InformServer)
                   1120:                                IRC_WriteStrServersPrefix(Origin, Client, "PART %s :%s", c->name, Reason);
                   1121:
                   1122:                        IRC_WriteStrChannelPrefix(Origin, c, Client, false, "PART %s :%s",
                   1123:                                                                        c->name, Reason);
                   1124:
                   1125:                        if ((Client_Conn(Origin) > NONE) &&
                   1126:                                        (Client_Type(Origin) == CLIENT_USER))
                   1127:                        {
                   1128:                                IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason);
                   1129:                                LogDebug("User \"%s\" left channel \"%s\" (%s).",
                   1130:                                        Client_Mask(Client), c->name, Reason);
                   1131:                        }
                   1132:        }
                   1133:
                   1134:        /* When channel is empty and is not pre-defined, delete */
                   1135:        if( ! Channel_HasMode( Chan, 'P' ))
                   1136:        {
                   1137:                if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
                   1138:        }
                   1139:
                   1140:        return true;
                   1141: } /* Remove_Client */
                   1142:
                   1143:
                   1144: GLOBAL bool
                   1145: Channel_AddBan(CHANNEL *c, const char *mask, const char *who )
                   1146: {
                   1147:        struct list_head *h = Channel_GetListBans(c);
                   1148:        LogDebug("Adding \"%s\" to \"%s\" ban list", mask, Channel_Name(c));
                   1149:        return Lists_Add(h, mask, time(NULL), who, false);
                   1150: }
                   1151:
                   1152:
                   1153: GLOBAL bool
                   1154: Channel_AddExcept(CHANNEL *c, const char *mask, const char *who )
                   1155: {
                   1156:        struct list_head *h = Channel_GetListExcepts(c);
                   1157:        LogDebug("Adding \"%s\" to \"%s\" exception list", mask, Channel_Name(c));
                   1158:        return Lists_Add(h, mask, time(NULL), who, false);
                   1159: }
                   1160:
                   1161:
                   1162: GLOBAL bool
                   1163: Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce, const char *who )
                   1164: {
                   1165:        struct list_head *h = Channel_GetListInvites(c);
                   1166:        LogDebug("Adding \"%s\" to \"%s\" invite list", mask, Channel_Name(c));
                   1167:        return Lists_Add(h, mask, time(NULL), who, onlyonce);
                   1168: }
                   1169:
                   1170:
                   1171: static bool
                   1172: ShowChannelList(struct list_head *head, CLIENT *Client, CHANNEL *Channel,
                   1173:                char *msg, char *msg_end)
                   1174: {
                   1175:        struct list_elem *e;
                   1176:
                   1177:        assert (Client != NULL);
                   1178:        assert (Channel != NULL);
                   1179:
                   1180:        e = Lists_GetFirst(head);
                   1181:        while (e) {
                   1182:                if (!IRC_WriteStrClient(Client, msg, Client_ID(Client),
                   1183:                                        Channel_Name(Channel),
                   1184:                                        Lists_GetMask(e),
                   1185:                                        Lists_GetReason(e),
                   1186:                                        Lists_GetValidity(e)))
                   1187:                        return DISCONNECTED;
                   1188:                e = Lists_GetNext(e);
                   1189:        }
                   1190:
                   1191:        return IRC_WriteStrClient(Client, msg_end, Client_ID(Client),
                   1192:                                  Channel_Name(Channel));
                   1193: }
                   1194:
                   1195:
                   1196: GLOBAL bool
                   1197: Channel_ShowBans( CLIENT *Client, CHANNEL *Channel )
                   1198: {
                   1199:        struct list_head *h;
                   1200:
                   1201:        assert( Channel != NULL );
                   1202:
                   1203:        h = Channel_GetListBans(Channel);
                   1204:        return ShowChannelList(h, Client, Channel, RPL_BANLIST_MSG,
                   1205:                               RPL_ENDOFBANLIST_MSG);
                   1206: }
                   1207:
                   1208:
                   1209: GLOBAL bool
                   1210: Channel_ShowExcepts( CLIENT *Client, CHANNEL *Channel )
                   1211: {
                   1212:        struct list_head *h;
                   1213:
                   1214:        assert( Channel != NULL );
                   1215:
                   1216:        h = Channel_GetListExcepts(Channel);
                   1217:        return ShowChannelList(h, Client, Channel, RPL_EXCEPTLIST_MSG,
                   1218:                               RPL_ENDOFEXCEPTLIST_MSG);
                   1219: }
                   1220:
                   1221:
                   1222: GLOBAL bool
                   1223: Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel )
                   1224: {
                   1225:        struct list_head *h;
                   1226:
                   1227:        assert( Channel != NULL );
                   1228:
                   1229:        h = Channel_GetListInvites(Channel);
                   1230:        return ShowChannelList(h, Client, Channel, RPL_INVITELIST_MSG,
                   1231:                               RPL_ENDOFINVITELIST_MSG);
                   1232: }
                   1233:
                   1234:
                   1235: /**
                   1236:  * Log a message to the local &SERVER channel, if it exists.
                   1237:  */
                   1238: GLOBAL void
                   1239: Channel_LogServer(const char *msg)
                   1240: {
                   1241:        CHANNEL *sc;
                   1242:        CLIENT *c;
                   1243:
                   1244:        assert(msg != NULL);
                   1245:
                   1246:        sc = Channel_Search("&SERVER");
                   1247:        if (!sc)
                   1248:                return;
                   1249:
                   1250:        c = Client_ThisServer();
                   1251:        Channel_Write(sc, c, c, "PRIVMSG", false, msg);
                   1252: } /* Channel_LogServer */
                   1253:
                   1254:
                   1255: GLOBAL bool
                   1256: Channel_CheckKey(CHANNEL *Chan, CLIENT *Client, const char *Key)
                   1257: {
                   1258:        char *file_name, line[COMMAND_LEN], *nick, *pass;
                   1259:        FILE *fd;
                   1260:
                   1261:        assert(Chan != NULL);
                   1262:        assert(Client != NULL);
                   1263:        assert(Key != NULL);
                   1264:
                   1265:        if (!Channel_HasMode(Chan, 'k'))
                   1266:                return true;
                   1267:        if (*Key == '\0')
                   1268:                return false;
                   1269:        if (strcmp(Chan->key, Key) == 0)
                   1270:                return true;
                   1271:
                   1272:        file_name = array_start(&Chan->keyfile);
                   1273:        if (!file_name)
                   1274:                return false;
                   1275:        fd = fopen(file_name, "r");
                   1276:        if (!fd) {
                   1277:                Log(LOG_ERR, "Can't open channel key file \"%s\" for %s: %s",
                   1278:                    file_name, Chan->name, strerror(errno));
                   1279:                return false;
                   1280:        }
                   1281:
                   1282:        while (fgets(line, (int)sizeof(line), fd) != NULL) {
                   1283:                ngt_TrimStr(line);
                   1284:                if (! (nick = strchr(line, ':')))
                   1285:                        continue;
                   1286:                *nick++ = '\0';
                   1287:                if (!Match(line, Client_User(Client)))
                   1288:                        continue;
                   1289:                if (! (pass = strchr(nick, ':')))
                   1290:                        continue;
                   1291:                *pass++ = '\0';
                   1292:                if (!Match(nick, Client_ID(Client)))
                   1293:                        continue;
                   1294:                if (strcmp(Key, pass) != 0)
                   1295:                        continue;
                   1296:
                   1297:                fclose(fd);
                   1298:                return true;
                   1299:        }
                   1300:        fclose(fd);
                   1301:        return false;
                   1302: } /* Channel_CheckKey */
                   1303:
                   1304:
                   1305: static CL2CHAN *
                   1306: Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
                   1307: {
                   1308:        return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan );
                   1309: } /* Get_First_Cl2Chan */
                   1310:
                   1311:
                   1312: static CL2CHAN *
                   1313: Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel )
                   1314: {
                   1315:        CL2CHAN *cl2chan;
                   1316:
                   1317:        assert( Client != NULL || Channel != NULL );
                   1318:
                   1319:        cl2chan = Start;
                   1320:        while( cl2chan )
                   1321:        {
                   1322:                if(( Client ) && ( cl2chan->client == Client )) return cl2chan;
                   1323:                if(( Channel ) && ( cl2chan->channel == Channel )) return cl2chan;
                   1324:                cl2chan = cl2chan->next;
                   1325:        }
                   1326:        return NULL;
                   1327: } /* Get_Next_Cl2Chan */
                   1328:
                   1329:
                   1330: /**
                   1331:  * Remove a channel and free all of its data structures.
                   1332:  */
                   1333: static void
                   1334: Delete_Channel(CHANNEL *Chan)
                   1335: {
                   1336:        CHANNEL *chan, *last_chan;
                   1337:
                   1338:        last_chan = NULL;
                   1339:        chan = My_Channels;
                   1340:        while (chan) {
                   1341:                if (chan == Chan)
                   1342:                        break;
                   1343:                last_chan = chan;
                   1344:                chan = chan->next;
                   1345:        }
                   1346:
                   1347:        assert(chan != NULL);
                   1348:        if (!chan)
                   1349:                return;
                   1350:
                   1351:        /* maintain channel list */
                   1352:        if (last_chan)
                   1353:                last_chan->next = chan->next;
                   1354:        else
                   1355:                My_Channels = chan->next;
                   1356:
                   1357:        LogDebug("Freed channel structure for \"%s\".", Chan->name);
                   1358:        Free_Channel(Chan);
                   1359: } /* Delete_Channel */
                   1360:
                   1361:
                   1362: static void
                   1363: Set_KeyFile(CHANNEL *Chan, const char *KeyFile)
                   1364: {
                   1365:        size_t len;
                   1366:
                   1367:        assert(Chan != NULL);
                   1368:        assert(KeyFile != NULL);
                   1369:
                   1370:        len = strlen(KeyFile);
                   1371:        if (len < array_bytes(&Chan->keyfile)) {
                   1372:                Log(LOG_INFO, "Channel key file of %s removed.", Chan->name);
                   1373:                array_free(&Chan->keyfile);
                   1374:        }
                   1375:
                   1376:        if (len < 1)
                   1377:                return;
                   1378:
                   1379:        if (!array_copyb(&Chan->keyfile, KeyFile, len+1))
                   1380:                Log(LOG_WARNING,
                   1381:                    "Could not set new channel key file \"%s\" for %s: %s",
                   1382:                    KeyFile, Chan->name, strerror(errno));
                   1383:        else
                   1384:                Log(LOG_INFO|LOG_snotice,
                   1385:                    "New local channel key file \"%s\" for %s activated.",
                   1386:                    KeyFile, Chan->name);
                   1387: } /* Set_KeyFile */
                   1388:
                   1389:
                   1390: /* -eof- */

CVSweb