X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fchannel.c;h=781d91a5a69ef13f12ec24b3210d46a955620ffb;hp=edbbc38bee3412d0c336833f34393bebab5323c8;hb=a3a4b5f6966c4378dc023ed37942e0e8f315aa56;hpb=9bc5d565bbbd1131aaa7608076598167036f261b diff --git a/src/ngircd/channel.c b/src/ngircd/channel.c index edbbc38b..781d91a5 100644 --- a/src/ngircd/channel.c +++ b/src/ngircd/channel.c @@ -1,22 +1,23 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2009 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. - * - * Channel management */ - #define __channel_c__ - #include "portab.h" +/** + * @file + * Channel management + */ + #include "imp.h" #include #include @@ -109,9 +110,12 @@ Channel_InitPredefined( void ) assert(channel_count == 0 || conf_chan != NULL); for (i = 0; i < channel_count; i++, conf_chan++) { - if (!conf_chan->name[0] || !Channel_IsValidName(conf_chan->name)) { - Log(LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"", - conf_chan->name); + if (!conf_chan->name[0]) + continue; + if (!Channel_IsValidName(conf_chan->name)) { + Log(LOG_ERR, + "Can't create pre-defined channel: invalid name: \"%s\"", + conf_chan->name); continue; } @@ -262,6 +266,9 @@ Channel_Part(CLIENT * Client, CLIENT * Origin, const char *Name, const char *Rea return false; } + if (Conf_MorePrivacy) + Reason = ""; + /* Part client from channel */ if (!Remove_Client(REMOVE_PART, chan, Client, Origin, Reason, true)) return false; @@ -330,6 +337,9 @@ Channel_Quit( CLIENT *Client, const char *Reason ) assert( Client != NULL ); assert( Reason != NULL ); + if (Conf_MorePrivacy) + Reason = ""; + IRC_WriteStrRelatedPrefix( Client, Client, false, "QUIT :%s", Reason ); c = My_Channels; @@ -342,20 +352,31 @@ Channel_Quit( CLIENT *Client, const char *Reason ) } /* Channel_Quit */ +/** + * Get number of channels this server knows and that are "visible" to + * the given client. If no client is given, all channels will be counted. + * + * @param Client The client to check or NULL. + * @return Number of channels visible to the client. + */ GLOBAL unsigned long -Channel_Count( void ) +Channel_CountVisible (CLIENT *Client) { CHANNEL *c; unsigned long count = 0; c = My_Channels; - while( c ) - { - count++; + while(c) { + if (Client) { + if (!strchr(Channel_Modes(c), 's') + || Channel_IsMemberOf(c, Client)) + count++; + } else + count++; c = c->next; } return count; -} /* Channel_Count */ +} GLOBAL unsigned long @@ -960,6 +981,9 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const ch Client_Mask( Client ), c->name, Client_ID(Origin), Reason); break; default: /* PART */ + if (Conf_MorePrivacy) + Reason = ""; + if (InformServer) IRC_WriteStrServersPrefix(Origin, Client, "PART %s :%s", c->name, Reason); @@ -989,7 +1013,8 @@ GLOBAL bool Channel_AddBan(CHANNEL *c, const char *mask ) { struct list_head *h = Channel_GetListBans(c); - return Lists_Add(h, mask, false); + LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "ban"); + return Lists_Add(h, mask, false, NULL); } @@ -997,29 +1022,31 @@ GLOBAL bool Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce) { struct list_head *h = Channel_GetListInvites(c); - return Lists_Add(h, mask, onlyonce); + LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "invite"); + return Lists_Add(h, mask, onlyonce, NULL); } static bool -ShowInvitesBans(struct list_head *head, CLIENT *Client, CHANNEL *Channel, bool invite) +ShowChannelList(struct list_head *head, CLIENT *Client, CHANNEL *Channel, + char *msg, char *msg_end) { struct list_elem *e; - char *msg = invite ? RPL_INVITELIST_MSG : RPL_BANLIST_MSG; - char *msg_end; - assert( Client != NULL ); - assert( Channel != NULL ); + assert (Client != NULL); + assert (Channel != NULL); e = Lists_GetFirst(head); while (e) { - if( ! IRC_WriteStrClient( Client, msg, Client_ID( Client ), - Channel_Name( Channel ), Lists_GetMask(e) )) return DISCONNECTED; + if (!IRC_WriteStrClient(Client, msg, Client_ID(Client), + Channel_Name(Channel), + Lists_GetMask(e))) + return DISCONNECTED; e = Lists_GetNext(e); } - msg_end = invite ? RPL_ENDOFINVITELIST_MSG : RPL_ENDOFBANLIST_MSG; - return IRC_WriteStrClient( Client, msg_end, Client_ID( Client ), Channel_Name( Channel )); + return IRC_WriteStrClient(Client, msg_end, Client_ID(Client), + Channel_Name(Channel)); } @@ -1031,7 +1058,8 @@ Channel_ShowBans( CLIENT *Client, CHANNEL *Channel ) assert( Channel != NULL ); h = Channel_GetListBans(Channel); - return ShowInvitesBans(h, Client, Channel, false); + return ShowChannelList(h, Client, Channel, RPL_BANLIST_MSG, + RPL_ENDOFBANLIST_MSG); } @@ -1043,7 +1071,8 @@ Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel ) assert( Channel != NULL ); h = Channel_GetListInvites(Channel); - return ShowInvitesBans(h, Client, Channel, true); + return ShowChannelList(h, Client, Channel, RPL_INVITELIST_MSG, + RPL_ENDOFINVITELIST_MSG); } @@ -1079,10 +1108,10 @@ Channel_CheckKey(CHANNEL *Chan, CLIENT *Client, const char *Key) if (!strchr(Chan->modes, 'k')) return true; - if (strcmp(Chan->key, Key) == 0) - return true; if (*Key == '\0') return false; + if (strcmp(Chan->key, Key) == 0) + return true; file_name = array_start(&Chan->keyfile); if (!file_name) @@ -1117,6 +1146,64 @@ Channel_CheckKey(CHANNEL *Chan, CLIENT *Client, const char *Key) } /* Channel_CheckKey */ +/** + * Check wether a client is allowed to administer a channel or not. + * + * @param Chan The channel to test. + * @param Client The client from which the command has been received. + * @param Origin The originator of the command (or NULL). + * @param OnChannel Set to true if the originator is member of the channel. + * @param AdminOk Set to true if the client is allowed to do + * administrative tasks on this channel. + * @param UseServerMode Set to true if ngIRCd should emulate "server mode", + * that is send commands as if originating from a server + * and not the originator of the command. + */ +GLOBAL void +Channel_CheckAdminRights(CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, + bool *OnChannel, bool *AdminOk, bool *UseServerMode) +{ + assert (Chan != NULL); + assert (Client != NULL); + assert (OnChannel != NULL); + assert (AdminOk != NULL); + assert (UseServerMode != NULL); + + /* Use the client as origin, if no origin has been given (no prefix?) */ + if (!Origin) + Origin = Client; + + *OnChannel = false; + *AdminOk = false; + *UseServerMode = false; + + if (Client_Type(Client) != CLIENT_USER + && Client_Type(Client) != CLIENT_SERVER + && Client_Type(Client) != CLIENT_SERVICE) + return; + + /* Allow channel administration if the client is a server or service */ + if (Client_Type(Client) != CLIENT_USER) { + *AdminOk = true; + return; + } + + *OnChannel = Channel_IsMemberOf(Chan, Origin); + + if (*OnChannel && strchr(Channel_UserModes(Chan, Origin), 'o')) { + /* User is a channel operator */ + *AdminOk = true; + } else if (Conf_OperCanMode) { + /* IRC operators are allowed to administer channels as well */ + if (Client_OperByMe(Origin)) { + *AdminOk = true; + if (Conf_OperServerMode) + *UseServerMode = true; + } + } +} /* Channel_CheckAdminRights */ + + static CL2CHAN * Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan ) {