/** * Part client from channel. * This function lets a client part from a channel. First, the function checks * if the channel exists and the client is a member of it and sends out * appropriate error messages if not. The real work is done by the function * Remove_Client(). */ GLOBAL bool Channel_Part(CLIENT * Client, CLIENT * Origin, const char *Name, const char *Reason) { CHANNEL *chan; assert(Client != NULL); assert(Name != NULL); assert(Reason != NULL); /* Check that specified channel exists */ chan = Channel_Search(Name); if (!chan) { IRC_WriteErrClient(Client, ERR_NOSUCHCHANNEL_MSG, Client_ID(Client), Name); return false; } /* Check that the client is in the channel */ if (!Get_Cl2Chan(chan, Client)) { IRC_WriteErrClient(Client, ERR_NOTONCHANNEL_MSG, Client_ID(Client), Name); return false; } if (Conf_MorePrivacy) Reason = ""; /* Part client from channel */ if (!Remove_Client(REMOVE_PART, chan, Client, Origin, Reason, true)) return false; else return true; } /* Channel_Part */
GLOBAL void Channel_Quit( CLIENT *Client, const char *Reason ) { CHANNEL *c, *next_c; assert( Client != NULL ); assert( Reason != NULL ); if (Conf_MorePrivacy) Reason = ""; IRC_WriteStrRelatedPrefix( Client, Client, false, "QUIT :%s", Reason ); c = My_Channels; while( c ) { next_c = c->next; Remove_Client( REMOVE_QUIT, c, Client, Client, Reason, false ); c = next_c; } } /* Channel_Quit */
/** * Kick user from Channel */ GLOBAL void Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name, const char *Reason ) { CHANNEL *chan; bool can_kick = false; assert(Peer != NULL); assert(Target != NULL); assert(Origin != NULL); assert(Name != NULL); assert(Reason != NULL); /* Check that channel exists */ chan = Channel_Search( Name ); if (!chan) { IRC_WriteErrClient(Origin, ERR_NOSUCHCHANNEL_MSG, Client_ID(Origin), Name); return; } if (Client_Type(Peer) != CLIENT_SERVER && Client_Type(Origin) != CLIENT_SERVICE) { /* Check that user is on the specified channel */ if (!Channel_IsMemberOf(chan, Origin)) { IRC_WriteErrClient(Origin, ERR_NOTONCHANNEL_MSG, Client_ID(Origin), Name); return; } } /* Check that the client to be kicked is on the specified channel */ if (!Channel_IsMemberOf(chan, Target)) { IRC_WriteErrClient(Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID(Origin), Client_ID(Target), Name ); return; } if(Client_Type(Peer) == CLIENT_USER) { /* Channel mode 'Q' and user mode 'q' on target: nobody but * IRC Operators and servers can kick the target user */ if ((Channel_HasMode(chan, 'Q') || Client_HasMode(Target, 'q') || Client_Type(Target) == CLIENT_SERVICE) && !Client_HasMode(Origin, 'o')) { IRC_WriteErrClient(Origin, ERR_KICKDENY_MSG, Client_ID(Origin), Name, Client_ID(Target)); return; } /* Check if client has the rights to kick target */ /* Owner can kick everyone */ if (Channel_UserHasMode(chan, Peer, 'q')) can_kick = true; /* Admin can't kick owner */ else if (Channel_UserHasMode(chan, Peer, 'a') && !Channel_UserHasMode(chan, Target, 'q')) can_kick = true; /* Op can't kick owner | admin */ else if (Channel_UserHasMode(chan, Peer, 'o') && !Channel_UserHasMode(chan, Target, 'q') && !Channel_UserHasMode(chan, Target, 'a')) can_kick = true; /* Half Op can't kick owner | admin | op */ else if (Channel_UserHasMode(chan, Peer, 'h') && !Channel_UserHasMode(chan, Target, 'q') && !Channel_UserHasMode(chan, Target, 'a') && !Channel_UserHasMode(chan, Target, 'o')) can_kick = true; /* IRC operators & IRCd with OperCanMode enabled * can kick anyways regardless of privilege */ else if(Client_HasMode(Origin, 'o') && Conf_OperCanMode) can_kick = true; if(!can_kick) { IRC_WriteErrClient(Origin, ERR_CHANOPPRIVTOOLOW_MSG, Client_ID(Origin), Name); return; } } /* Kick Client from channel */ Remove_Client( REMOVE_KICK, chan, Target, Origin, Reason, true); } /* Channel_Kick */
/** * Kick user from Channel */ GLOBAL void Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name, const char *Reason ) { CHANNEL *chan; char *ptr, *target_modes; bool can_kick = false; assert(Peer != NULL); assert(Target != NULL); assert(Origin != NULL); assert(Name != NULL); assert(Reason != NULL); /* Check that channel exists */ chan = Channel_Search( Name ); if( ! chan ) { IRC_WriteStrClient( Origin, ERR_NOSUCHCHANNEL_MSG, Client_ID( Origin ), Name ); return; } if (Client_Type(Peer) != CLIENT_SERVER && Client_Type(Origin) != CLIENT_SERVICE) { /* Check that user is on the specified channel */ if (!Channel_IsMemberOf(chan, Origin)) { IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID(Origin), Name); return; } } if(Client_Type(Peer) == CLIENT_USER) { /* Channel mode 'Q' and user mode 'q' on target: nobody but * IRC Operators and servers can kick the target user */ if ((strchr(Channel_Modes(chan), 'Q') || Client_HasMode(Target, 'q') || Client_Type(Target) == CLIENT_SERVICE) && !Client_HasMode(Origin, 'o')) { IRC_WriteStrClient(Origin, ERR_KICKDENY_MSG, Client_ID(Origin), Name, Client_ID(Target)); return; } /* Check if client has the rights to kick target */ ptr = Channel_UserModes(chan, Peer); target_modes = Channel_UserModes(chan, Target); while(*ptr) { /* Owner can kick everyone */ if ( *ptr == 'q') { can_kick = true; break; } /* Admin can't kick owner */ if ( *ptr == 'a' ) { if (!strchr(target_modes, 'q')) { can_kick = true; break; } } /* Op can't kick owner | admin */ if ( *ptr == 'o' ) { if (!strchr(target_modes, 'q') && !strchr(target_modes, 'a')) { can_kick = true; break; } } /* Half Op can't kick owner | admin | op */ if ( *ptr == 'h' ) { if (!strchr(target_modes, 'q') && !strchr(target_modes, 'a') && !strchr(target_modes, 'o')) { can_kick = true; break; } } ptr++; } if(!can_kick) { IRC_WriteStrClient(Origin, ERR_CHANOPPRIVTOOLOW_MSG, Client_ID(Origin), Name); return; } } /* Check that the client to be kicked is on the specified channel */ if (!Channel_IsMemberOf(chan, Target)) { IRC_WriteStrClient(Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID(Origin), Client_ID(Target), Name ); return; } /* Kick Client from channel */ Remove_Client( REMOVE_KICK, chan, Target, Origin, Reason, true); } /* Channel_Kick */